mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 10:28:10 +00:00
LibWeb: Basic implementation of global event handlers :^)
Document and HTMLElement now inherit from HTML::GlobalEventHandlers which allows them to support "onfoo" event handler attributes. These are assignable both via IDL attributes and content attributes. Event listeners constructed this way get a special "attribute" flag on them so we know which one to replace if you reassign them. This also allows them to coexist with EventTarget.addEventListener(). This is all a bit sloppy, but it works decently for a first cut. The Window object should also inherit GlobalEventHandlers, but since we don't generate it from IDL, I haven't taken that step here. Also this would be a lot nicer if we supported IDL mixins.
This commit is contained in:
parent
b43db4cc50
commit
a59b1825ce
15 changed files with 391 additions and 2 deletions
|
@ -55,6 +55,7 @@ set(SOURCES
|
||||||
HTML/AttributeNames.cpp
|
HTML/AttributeNames.cpp
|
||||||
HTML/CanvasRenderingContext2D.cpp
|
HTML/CanvasRenderingContext2D.cpp
|
||||||
HTML/EventNames.cpp
|
HTML/EventNames.cpp
|
||||||
|
HTML/GlobalEventHandlers.cpp
|
||||||
HTML/HTMLAnchorElement.cpp
|
HTML/HTMLAnchorElement.cpp
|
||||||
HTML/HTMLAreaElement.cpp
|
HTML/HTMLAreaElement.cpp
|
||||||
HTML/HTMLAudioElement.cpp
|
HTML/HTMLAudioElement.cpp
|
||||||
|
|
|
@ -904,6 +904,7 @@ void generate_prototype_implementation(const IDL::Interface& interface)
|
||||||
#include <LibWeb/DOM/Element.h>
|
#include <LibWeb/DOM/Element.h>
|
||||||
#include <LibWeb/DOM/EventListener.h>
|
#include <LibWeb/DOM/EventListener.h>
|
||||||
#include <LibWeb/DOM/Window.h>
|
#include <LibWeb/DOM/Window.h>
|
||||||
|
#include <LibWeb/HTML/EventHandler.h>
|
||||||
#include <LibWeb/HTML/HTMLElement.h>
|
#include <LibWeb/HTML/HTMLElement.h>
|
||||||
#include <LibWeb/NavigationTiming/PerformanceTiming.h>
|
#include <LibWeb/NavigationTiming/PerformanceTiming.h>
|
||||||
#include <LibWeb/Origin.h>
|
#include <LibWeb/Origin.h>
|
||||||
|
@ -1096,6 +1097,18 @@ static @fully_qualified_name@* impl_from(JS::VM& vm, JS::GlobalObject& global_ob
|
||||||
auto @cpp_name@ = @js_name@@js_suffix@.to_u32(global_object);
|
auto @cpp_name@ = @js_name@@js_suffix@.to_u32(global_object);
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
@return_statement@
|
@return_statement@
|
||||||
|
)~~~");
|
||||||
|
} else if (parameter.type.name == "EventHandler") {
|
||||||
|
// x.onfoo = function() { ... }
|
||||||
|
scoped_generator.append(R"~~~(
|
||||||
|
HTML::EventHandler @cpp_name@;
|
||||||
|
if (@js_name@@js_suffix@.is_function()) {
|
||||||
|
@cpp_name@.callback = JS::make_handle(&@js_name@@js_suffix@.as_function());
|
||||||
|
} else if (@js_name@@js_suffix@.is_string()) {
|
||||||
|
@cpp_name@.string = @js_name@@js_suffix@.as_string().string();
|
||||||
|
} else {
|
||||||
|
@return_statement@
|
||||||
|
}
|
||||||
)~~~");
|
)~~~");
|
||||||
} else {
|
} else {
|
||||||
dbgln("Unimplemented JS-to-C++ conversion: {}", parameter.type.name);
|
dbgln("Unimplemented JS-to-C++ conversion: {}", parameter.type.name);
|
||||||
|
@ -1173,6 +1186,10 @@ static @fully_qualified_name@* impl_from(JS::VM& vm, JS::GlobalObject& global_ob
|
||||||
} else if (return_type.name == "Uint8ClampedArray") {
|
} else if (return_type.name == "Uint8ClampedArray") {
|
||||||
scoped_generator.append(R"~~~(
|
scoped_generator.append(R"~~~(
|
||||||
return retval;
|
return retval;
|
||||||
|
)~~~");
|
||||||
|
} else if (return_type.name == "EventHandler") {
|
||||||
|
scoped_generator.append(R"~~~(
|
||||||
|
return retval.callback.cell();
|
||||||
)~~~");
|
)~~~");
|
||||||
} else {
|
} else {
|
||||||
scoped_generator.append(R"~~~(
|
scoped_generator.append(R"~~~(
|
||||||
|
|
|
@ -55,6 +55,7 @@ enum class QuirksMode {
|
||||||
class Document
|
class Document
|
||||||
: public ParentNode
|
: public ParentNode
|
||||||
, public NonElementParentNode<Document>
|
, public NonElementParentNode<Document>
|
||||||
|
, public HTML::GlobalEventHandlers
|
||||||
, public Bindings::ScriptExecutionContext {
|
, public Bindings::ScriptExecutionContext {
|
||||||
public:
|
public:
|
||||||
using WrapperType = Bindings::DocumentWrapper;
|
using WrapperType = Bindings::DocumentWrapper;
|
||||||
|
@ -233,8 +234,12 @@ public:
|
||||||
private:
|
private:
|
||||||
explicit Document(const URL&);
|
explicit Document(const URL&);
|
||||||
|
|
||||||
|
// ^DOM::Node
|
||||||
virtual RefPtr<Layout::Node> create_layout_node() override;
|
virtual RefPtr<Layout::Node> create_layout_node() override;
|
||||||
|
|
||||||
|
// ^HTML::GlobalEventHandlers
|
||||||
|
virtual EventTarget& global_event_handlers_to_event_target() final { return *this; }
|
||||||
|
|
||||||
void tear_down_layout_tree();
|
void tear_down_layout_tree();
|
||||||
|
|
||||||
void increment_referencing_node_count()
|
void increment_referencing_node_count()
|
||||||
|
|
|
@ -36,4 +36,75 @@ interface Document : Node {
|
||||||
|
|
||||||
attribute DOMString title;
|
attribute DOMString title;
|
||||||
|
|
||||||
|
// FIXME: These should all come from a GlobalEventHandlers mixin
|
||||||
|
attribute EventHandler onabort;
|
||||||
|
attribute EventHandler onauxclick;
|
||||||
|
attribute EventHandler onblur;
|
||||||
|
attribute EventHandler oncancel;
|
||||||
|
attribute EventHandler oncanplay;
|
||||||
|
attribute EventHandler oncanplaythrough;
|
||||||
|
attribute EventHandler onchange;
|
||||||
|
attribute EventHandler onclick;
|
||||||
|
attribute EventHandler onclose;
|
||||||
|
attribute EventHandler oncontextmenu;
|
||||||
|
attribute EventHandler oncuechange;
|
||||||
|
attribute EventHandler ondblclick;
|
||||||
|
attribute EventHandler ondrag;
|
||||||
|
attribute EventHandler ondragend;
|
||||||
|
attribute EventHandler ondragenter;
|
||||||
|
attribute EventHandler ondragleave;
|
||||||
|
attribute EventHandler ondragover;
|
||||||
|
attribute EventHandler ondragstart;
|
||||||
|
attribute EventHandler ondrop;
|
||||||
|
attribute EventHandler ondurationchange;
|
||||||
|
attribute EventHandler onemptied;
|
||||||
|
attribute EventHandler onended;
|
||||||
|
|
||||||
|
// FIXME: Should be an OnErrorEventHandler
|
||||||
|
attribute EventHandler onerror;
|
||||||
|
|
||||||
|
attribute EventHandler onfocus;
|
||||||
|
attribute EventHandler onformdata;
|
||||||
|
attribute EventHandler oninput;
|
||||||
|
attribute EventHandler oninvalid;
|
||||||
|
attribute EventHandler onkeydown;
|
||||||
|
attribute EventHandler onkeypress;
|
||||||
|
attribute EventHandler onkeyup;
|
||||||
|
attribute EventHandler onload;
|
||||||
|
attribute EventHandler onloadeddata;
|
||||||
|
attribute EventHandler onloadedmetadata;
|
||||||
|
attribute EventHandler onloadstart;
|
||||||
|
attribute EventHandler onmousedown;
|
||||||
|
[LegacyLenientThis] attribute EventHandler onmouseenter;
|
||||||
|
[LegacyLenientThis] attribute EventHandler onmouseleave;
|
||||||
|
attribute EventHandler onmousemove;
|
||||||
|
attribute EventHandler onmouseout;
|
||||||
|
attribute EventHandler onmouseover;
|
||||||
|
attribute EventHandler onmouseup;
|
||||||
|
attribute EventHandler onpause;
|
||||||
|
attribute EventHandler onplay;
|
||||||
|
attribute EventHandler onplaying;
|
||||||
|
attribute EventHandler onprogress;
|
||||||
|
attribute EventHandler onratechange;
|
||||||
|
attribute EventHandler onreset;
|
||||||
|
attribute EventHandler onresize;
|
||||||
|
attribute EventHandler onscroll;
|
||||||
|
attribute EventHandler onsecuritypolicyviolation;
|
||||||
|
attribute EventHandler onseeked;
|
||||||
|
attribute EventHandler onseeking;
|
||||||
|
attribute EventHandler onselect;
|
||||||
|
attribute EventHandler onslotchange;
|
||||||
|
attribute EventHandler onstalled;
|
||||||
|
attribute EventHandler onsubmit;
|
||||||
|
attribute EventHandler onsuspend;
|
||||||
|
attribute EventHandler ontimeupdate;
|
||||||
|
attribute EventHandler ontoggle;
|
||||||
|
attribute EventHandler onvolumechange;
|
||||||
|
attribute EventHandler onwaiting;
|
||||||
|
attribute EventHandler onwebkitanimationend;
|
||||||
|
attribute EventHandler onwebkitanimationiteration;
|
||||||
|
attribute EventHandler onwebkitanimationstart;
|
||||||
|
attribute EventHandler onwebkittransitionend;
|
||||||
|
attribute EventHandler onwheel;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,8 +38,9 @@ class EventListener
|
||||||
public:
|
public:
|
||||||
using WrapperType = Bindings::EventListenerWrapper;
|
using WrapperType = Bindings::EventListenerWrapper;
|
||||||
|
|
||||||
explicit EventListener(JS::Handle<JS::Function> function)
|
explicit EventListener(JS::Handle<JS::Function> function, bool is_attribute = false)
|
||||||
: m_function(move(function))
|
: m_function(move(function))
|
||||||
|
, m_attribute(is_attribute)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +61,8 @@ public:
|
||||||
bool removed() const { return m_removed; }
|
bool removed() const { return m_removed; }
|
||||||
void set_removed(bool removed) { m_removed = removed; }
|
void set_removed(bool removed) { m_removed = removed; }
|
||||||
|
|
||||||
|
bool is_attribute() const { return m_attribute; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FlyString m_type;
|
FlyString m_type;
|
||||||
JS::Handle<JS::Function> m_function;
|
JS::Handle<JS::Function> m_function;
|
||||||
|
@ -67,6 +70,7 @@ private:
|
||||||
bool m_passive { false };
|
bool m_passive { false };
|
||||||
bool m_once { false };
|
bool m_once { false };
|
||||||
bool m_removed { false };
|
bool m_removed { false };
|
||||||
|
bool m_attribute { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ public:
|
||||||
NonnullRefPtr<EventListener> listener;
|
NonnullRefPtr<EventListener> listener;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Vector<EventListenerRegistration>& listeners() { return m_listeners; }
|
||||||
const Vector<EventListenerRegistration>& listeners() const { return m_listeners; }
|
const Vector<EventListenerRegistration>& listeners() const { return m_listeners; }
|
||||||
|
|
||||||
Function<void(const Event&)> activation_behaviour;
|
Function<void(const Event&)> activation_behaviour;
|
||||||
|
|
|
@ -62,6 +62,7 @@ enum class QuirksMode;
|
||||||
|
|
||||||
namespace Web::HTML {
|
namespace Web::HTML {
|
||||||
class CanvasRenderingContext2D;
|
class CanvasRenderingContext2D;
|
||||||
|
class EventHandler;
|
||||||
class HTMLAnchorElement;
|
class HTMLAnchorElement;
|
||||||
class HTMLAreaElement;
|
class HTMLAreaElement;
|
||||||
class HTMLAudioElement;
|
class HTMLAudioElement;
|
||||||
|
|
54
Userland/Libraries/LibWeb/HTML/EventHandler.h
Normal file
54
Userland/Libraries/LibWeb/HTML/EventHandler.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
||||||
|
* 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 <AK/String.h>
|
||||||
|
#include <LibJS/Heap/Handle.h>
|
||||||
|
#include <LibJS/Runtime/Function.h>
|
||||||
|
|
||||||
|
namespace Web::HTML {
|
||||||
|
|
||||||
|
struct EventHandler {
|
||||||
|
EventHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EventHandler(String s)
|
||||||
|
: string(move(s))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EventHandler(JS::Handle<JS::Function> c)
|
||||||
|
: callback(move(c))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
String string;
|
||||||
|
JS::Handle<JS::Function> callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
99
Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.cpp
Normal file
99
Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.cpp
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Interpreter.h>
|
||||||
|
#include <LibJS/Parser.h>
|
||||||
|
#include <LibJS/Runtime/ScriptFunction.h>
|
||||||
|
#include <LibWeb/DOM/Document.h>
|
||||||
|
#include <LibWeb/DOM/EventListener.h>
|
||||||
|
#include <LibWeb/HTML/EventHandler.h>
|
||||||
|
#include <LibWeb/HTML/EventNames.h>
|
||||||
|
#include <LibWeb/HTML/GlobalEventHandlers.h>
|
||||||
|
#include <LibWeb/UIEvents/EventNames.h>
|
||||||
|
|
||||||
|
namespace Web::HTML {
|
||||||
|
|
||||||
|
#undef __ENUMERATE
|
||||||
|
#define __ENUMERATE(attribute_name, event_name) \
|
||||||
|
void GlobalEventHandlers::set_##attribute_name(HTML::EventHandler value) \
|
||||||
|
{ \
|
||||||
|
set_event_handler_attribute(event_name, move(value)); \
|
||||||
|
} \
|
||||||
|
HTML::EventHandler GlobalEventHandlers::attribute_name() \
|
||||||
|
{ \
|
||||||
|
return get_event_handler_attribute(event_name); \
|
||||||
|
}
|
||||||
|
ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE)
|
||||||
|
#undef __ENUMERATE
|
||||||
|
|
||||||
|
GlobalEventHandlers::~GlobalEventHandlers()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalEventHandlers::set_event_handler_attribute(const FlyString& name, HTML::EventHandler value)
|
||||||
|
{
|
||||||
|
auto& self = global_event_handlers_to_event_target();
|
||||||
|
|
||||||
|
RefPtr<DOM::EventListener> listener;
|
||||||
|
if (!value.callback.is_null()) {
|
||||||
|
listener = adopt(*new DOM::EventListener(move(value.callback)));
|
||||||
|
} else {
|
||||||
|
StringBuilder builder;
|
||||||
|
builder.appendff("function {}(event) {{\n{}\n}}", name, value.string);
|
||||||
|
auto parser = JS::Parser(JS::Lexer(builder.string_view()));
|
||||||
|
auto program = parser.parse_function_node<JS::FunctionExpression>();
|
||||||
|
if (parser.has_errors()) {
|
||||||
|
dbgln("Failed to parse script in event handler attribute '{}'", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto* function = JS::ScriptFunction::create(self.script_execution_context()->interpreter().global_object(), name, program->body(), program->parameters(), program->function_length(), nullptr, false, false);
|
||||||
|
ASSERT(function);
|
||||||
|
listener = adopt(*new DOM::EventListener(JS::make_handle(static_cast<JS::Function*>(function))));
|
||||||
|
}
|
||||||
|
if (listener) {
|
||||||
|
for (auto& registered_listener : self.listeners()) {
|
||||||
|
if (registered_listener.event_name == name && registered_listener.listener->is_attribute()) {
|
||||||
|
self.remove_event_listener(name, registered_listener.listener);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.add_event_listener(name, listener.release_nonnull());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HTML::EventHandler GlobalEventHandlers::get_event_handler_attribute(const FlyString& name)
|
||||||
|
{
|
||||||
|
auto& self = global_event_handlers_to_event_target();
|
||||||
|
for (auto& listener : self.listeners()) {
|
||||||
|
if (listener.event_name == name && listener.listener->is_attribute()) {
|
||||||
|
return HTML::EventHandler { JS::make_handle(&listener.listener->function()) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -26,6 +26,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Forward.h>
|
||||||
|
#include <LibWeb/Forward.h>
|
||||||
|
|
||||||
#define ENUMERATE_GLOBAL_EVENT_HANDLERS(E) \
|
#define ENUMERATE_GLOBAL_EVENT_HANDLERS(E) \
|
||||||
E(onabort, HTML::EventNames::abort) \
|
E(onabort, HTML::EventNames::abort) \
|
||||||
E(onauxclick, "auxclick") \
|
E(onauxclick, "auxclick") \
|
||||||
|
@ -93,3 +96,25 @@
|
||||||
E(onwebkitanimationstart, "webkitanimationstart") \
|
E(onwebkitanimationstart, "webkitanimationstart") \
|
||||||
E(onwebkittransitionend, "webkittransitionend") \
|
E(onwebkittransitionend, "webkittransitionend") \
|
||||||
E(onwheel, "wheel")
|
E(onwheel, "wheel")
|
||||||
|
|
||||||
|
namespace Web::HTML {
|
||||||
|
|
||||||
|
class GlobalEventHandlers {
|
||||||
|
public:
|
||||||
|
virtual ~GlobalEventHandlers();
|
||||||
|
|
||||||
|
#undef __ENUMERATE
|
||||||
|
#define __ENUMERATE(attribute_name, event_name) \
|
||||||
|
void set_##attribute_name(HTML::EventHandler); \
|
||||||
|
HTML::EventHandler attribute_name();
|
||||||
|
ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE)
|
||||||
|
#undef __ENUMERATE
|
||||||
|
|
||||||
|
void set_event_handler_attribute(const FlyString& name, HTML::EventHandler);
|
||||||
|
HTML::EventHandler get_event_handler_attribute(const FlyString& name);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual DOM::EventTarget& global_event_handlers_to_event_target() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <LibWeb/CSS/StyleProperties.h>
|
#include <LibWeb/CSS/StyleProperties.h>
|
||||||
#include <LibWeb/CSS/StyleValue.h>
|
#include <LibWeb/CSS/StyleValue.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
|
#include <LibWeb/DOM/Window.h>
|
||||||
#include <LibWeb/HTML/HTMLBodyElement.h>
|
#include <LibWeb/HTML/HTMLBodyElement.h>
|
||||||
|
|
||||||
namespace Web::HTML {
|
namespace Web::HTML {
|
||||||
|
@ -78,4 +79,10 @@ void HTMLBodyElement::parse_attribute(const FlyString& name, const String& value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DOM::EventTarget& HTMLBodyElement::global_event_handlers_to_event_target()
|
||||||
|
{
|
||||||
|
// NOTE: This is a little weird, but IIUC document.body.onload actually refers to window.onload
|
||||||
|
return document().window();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,9 @@ public:
|
||||||
virtual void apply_presentational_hints(CSS::StyleProperties&) const override;
|
virtual void apply_presentational_hints(CSS::StyleProperties&) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// ^HTML::GlobalEventHandlers
|
||||||
|
virtual EventTarget& global_event_handlers_to_event_target() override;
|
||||||
|
|
||||||
RefPtr<CSS::ImageStyleValue> m_background_style_value;
|
RefPtr<CSS::ImageStyleValue> m_background_style_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,17 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
|
#include <LibJS/Interpreter.h>
|
||||||
|
#include <LibJS/Parser.h>
|
||||||
|
#include <LibJS/Runtime/ScriptFunction.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
|
#include <LibWeb/DOM/EventListener.h>
|
||||||
|
#include <LibWeb/HTML/EventHandler.h>
|
||||||
#include <LibWeb/HTML/HTMLAnchorElement.h>
|
#include <LibWeb/HTML/HTMLAnchorElement.h>
|
||||||
#include <LibWeb/HTML/HTMLElement.h>
|
#include <LibWeb/HTML/HTMLElement.h>
|
||||||
#include <LibWeb/Layout/BreakNode.h>
|
#include <LibWeb/Layout/BreakNode.h>
|
||||||
#include <LibWeb/Layout/TextNode.h>
|
#include <LibWeb/Layout/TextNode.h>
|
||||||
|
#include <LibWeb/UIEvents/EventNames.h>
|
||||||
|
|
||||||
namespace Web::HTML {
|
namespace Web::HTML {
|
||||||
|
|
||||||
|
@ -138,4 +144,17 @@ bool HTMLElement::cannot_navigate() const
|
||||||
return !is<HTML::HTMLAnchorElement>(this) && !is_connected();
|
return !is<HTML::HTMLAnchorElement>(this) && !is_connected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HTMLElement::parse_attribute(const FlyString& name, const String& value)
|
||||||
|
{
|
||||||
|
Element::parse_attribute(name, value);
|
||||||
|
|
||||||
|
#undef __ENUMERATE
|
||||||
|
#define __ENUMERATE(attribute_name, event_name) \
|
||||||
|
if (name == HTML::AttributeNames::attribute_name) { \
|
||||||
|
set_event_handler_attribute(event_name, EventHandler { value }); \
|
||||||
|
}
|
||||||
|
ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE)
|
||||||
|
#undef __ENUMERATE
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <LibWeb/DOM/Element.h>
|
#include <LibWeb/DOM/Element.h>
|
||||||
|
#include <LibWeb/HTML/EventNames.h>
|
||||||
|
#include <LibWeb/HTML/GlobalEventHandlers.h>
|
||||||
|
|
||||||
namespace Web::HTML {
|
namespace Web::HTML {
|
||||||
|
|
||||||
class HTMLElement : public DOM::Element {
|
class HTMLElement
|
||||||
|
: public DOM::Element
|
||||||
|
, public HTML::GlobalEventHandlers {
|
||||||
public:
|
public:
|
||||||
using WrapperType = Bindings::HTMLElementWrapper;
|
using WrapperType = Bindings::HTMLElementWrapper;
|
||||||
|
|
||||||
|
@ -48,7 +52,13 @@ public:
|
||||||
|
|
||||||
bool cannot_navigate() const;
|
bool cannot_navigate() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void parse_attribute(const FlyString& name, const String& value) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// ^HTML::GlobalEventHandlers
|
||||||
|
virtual EventTarget& global_event_handlers_to_event_target() override { return *this; }
|
||||||
|
|
||||||
enum class ContentEditableState {
|
enum class ContentEditableState {
|
||||||
True,
|
True,
|
||||||
False,
|
False,
|
||||||
|
|
|
@ -8,4 +8,76 @@ interface HTMLElement : Element {
|
||||||
attribute DOMString contentEditable;
|
attribute DOMString contentEditable;
|
||||||
|
|
||||||
[LegacyNullToEmptyString] attribute DOMString innerText;
|
[LegacyNullToEmptyString] attribute DOMString innerText;
|
||||||
|
|
||||||
|
// FIXME: These should all come from a GlobalEventHandlers mixin
|
||||||
|
attribute EventHandler onabort;
|
||||||
|
attribute EventHandler onauxclick;
|
||||||
|
attribute EventHandler onblur;
|
||||||
|
attribute EventHandler oncancel;
|
||||||
|
attribute EventHandler oncanplay;
|
||||||
|
attribute EventHandler oncanplaythrough;
|
||||||
|
attribute EventHandler onchange;
|
||||||
|
attribute EventHandler onclick;
|
||||||
|
attribute EventHandler onclose;
|
||||||
|
attribute EventHandler oncontextmenu;
|
||||||
|
attribute EventHandler oncuechange;
|
||||||
|
attribute EventHandler ondblclick;
|
||||||
|
attribute EventHandler ondrag;
|
||||||
|
attribute EventHandler ondragend;
|
||||||
|
attribute EventHandler ondragenter;
|
||||||
|
attribute EventHandler ondragleave;
|
||||||
|
attribute EventHandler ondragover;
|
||||||
|
attribute EventHandler ondragstart;
|
||||||
|
attribute EventHandler ondrop;
|
||||||
|
attribute EventHandler ondurationchange;
|
||||||
|
attribute EventHandler onemptied;
|
||||||
|
attribute EventHandler onended;
|
||||||
|
|
||||||
|
// FIXME: Should be an OnErrorEventHandler
|
||||||
|
attribute EventHandler onerror;
|
||||||
|
|
||||||
|
attribute EventHandler onfocus;
|
||||||
|
attribute EventHandler onformdata;
|
||||||
|
attribute EventHandler oninput;
|
||||||
|
attribute EventHandler oninvalid;
|
||||||
|
attribute EventHandler onkeydown;
|
||||||
|
attribute EventHandler onkeypress;
|
||||||
|
attribute EventHandler onkeyup;
|
||||||
|
attribute EventHandler onload;
|
||||||
|
attribute EventHandler onloadeddata;
|
||||||
|
attribute EventHandler onloadedmetadata;
|
||||||
|
attribute EventHandler onloadstart;
|
||||||
|
attribute EventHandler onmousedown;
|
||||||
|
[LegacyLenientThis] attribute EventHandler onmouseenter;
|
||||||
|
[LegacyLenientThis] attribute EventHandler onmouseleave;
|
||||||
|
attribute EventHandler onmousemove;
|
||||||
|
attribute EventHandler onmouseout;
|
||||||
|
attribute EventHandler onmouseover;
|
||||||
|
attribute EventHandler onmouseup;
|
||||||
|
attribute EventHandler onpause;
|
||||||
|
attribute EventHandler onplay;
|
||||||
|
attribute EventHandler onplaying;
|
||||||
|
attribute EventHandler onprogress;
|
||||||
|
attribute EventHandler onratechange;
|
||||||
|
attribute EventHandler onreset;
|
||||||
|
attribute EventHandler onresize;
|
||||||
|
attribute EventHandler onscroll;
|
||||||
|
attribute EventHandler onsecuritypolicyviolation;
|
||||||
|
attribute EventHandler onseeked;
|
||||||
|
attribute EventHandler onseeking;
|
||||||
|
attribute EventHandler onselect;
|
||||||
|
attribute EventHandler onslotchange;
|
||||||
|
attribute EventHandler onstalled;
|
||||||
|
attribute EventHandler onsubmit;
|
||||||
|
attribute EventHandler onsuspend;
|
||||||
|
attribute EventHandler ontimeupdate;
|
||||||
|
attribute EventHandler ontoggle;
|
||||||
|
attribute EventHandler onvolumechange;
|
||||||
|
attribute EventHandler onwaiting;
|
||||||
|
attribute EventHandler onwebkitanimationend;
|
||||||
|
attribute EventHandler onwebkitanimationiteration;
|
||||||
|
attribute EventHandler onwebkitanimationstart;
|
||||||
|
attribute EventHandler onwebkittransitionend;
|
||||||
|
attribute EventHandler onwheel;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue