diff options
author | Andreas Kling <kling@serenityos.org> | 2021-02-03 22:47:50 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-02-03 23:03:05 +0100 |
commit | a59b1825ce3ba5d6e6adf51ab2745c7212789c31 (patch) | |
tree | 8d7a09b0705fa05bb1d0921bf8400ca7d0aaa241 /Userland/Libraries/LibWeb | |
parent | b43db4cc5027c7aa1c4780a8ab2851f4a5f1cca0 (diff) | |
download | serenity-a59b1825ce3ba5d6e6adf51ab2745c7212789c31.zip |
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.
Diffstat (limited to 'Userland/Libraries/LibWeb')
-rw-r--r-- | Userland/Libraries/LibWeb/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp | 17 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.h | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.idl | 71 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/EventListener.h | 6 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/EventTarget.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Forward.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/EventHandler.h | 54 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.cpp | 99 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h | 25 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp | 7 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/HTMLElement.cpp | 19 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/HTMLElement.h | 12 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/HTMLElement.idl | 72 |
15 files changed, 391 insertions, 2 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index e61f263f26..14b458640c 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -55,6 +55,7 @@ set(SOURCES HTML/AttributeNames.cpp HTML/CanvasRenderingContext2D.cpp HTML/EventNames.cpp + HTML/GlobalEventHandlers.cpp HTML/HTMLAnchorElement.cpp HTML/HTMLAreaElement.cpp HTML/HTMLAudioElement.cpp diff --git a/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp b/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp index 39e8ac2bdd..06213342ad 100644 --- a/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp +++ b/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp @@ -904,6 +904,7 @@ void generate_prototype_implementation(const IDL::Interface& interface) #include <LibWeb/DOM/Element.h> #include <LibWeb/DOM/EventListener.h> #include <LibWeb/DOM/Window.h> +#include <LibWeb/HTML/EventHandler.h> #include <LibWeb/HTML/HTMLElement.h> #include <LibWeb/NavigationTiming/PerformanceTiming.h> #include <LibWeb/Origin.h> @@ -1097,6 +1098,18 @@ static @fully_qualified_name@* impl_from(JS::VM& vm, JS::GlobalObject& global_ob if (vm.exception()) @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 { dbgln("Unimplemented JS-to-C++ conversion: {}", parameter.type.name); ASSERT_NOT_REACHED(); @@ -1174,6 +1187,10 @@ static @fully_qualified_name@* impl_from(JS::VM& vm, JS::GlobalObject& global_ob scoped_generator.append(R"~~~( return retval; )~~~"); + } else if (return_type.name == "EventHandler") { + scoped_generator.append(R"~~~( + return retval.callback.cell(); +)~~~"); } else { scoped_generator.append(R"~~~( return wrap(global_object, const_cast<@return_type@&>(*retval)); diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index be7050b2cc..0f19fefdfd 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -55,6 +55,7 @@ enum class QuirksMode { class Document : public ParentNode , public NonElementParentNode<Document> + , public HTML::GlobalEventHandlers , public Bindings::ScriptExecutionContext { public: using WrapperType = Bindings::DocumentWrapper; @@ -233,8 +234,12 @@ public: private: explicit Document(const URL&); + // ^DOM::Node 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 increment_referencing_node_count() diff --git a/Userland/Libraries/LibWeb/DOM/Document.idl b/Userland/Libraries/LibWeb/DOM/Document.idl index 9aa2878d62..bd405a48bb 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.idl +++ b/Userland/Libraries/LibWeb/DOM/Document.idl @@ -36,4 +36,75 @@ interface Document : Node { 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; + }; diff --git a/Userland/Libraries/LibWeb/DOM/EventListener.h b/Userland/Libraries/LibWeb/DOM/EventListener.h index 1d5705c2b6..377d3899be 100644 --- a/Userland/Libraries/LibWeb/DOM/EventListener.h +++ b/Userland/Libraries/LibWeb/DOM/EventListener.h @@ -38,8 +38,9 @@ class EventListener public: 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_attribute(is_attribute) { } @@ -60,6 +61,8 @@ public: bool removed() const { return m_removed; } void set_removed(bool removed) { m_removed = removed; } + bool is_attribute() const { return m_attribute; } + private: FlyString m_type; JS::Handle<JS::Function> m_function; @@ -67,6 +70,7 @@ private: bool m_passive { false }; bool m_once { false }; bool m_removed { false }; + bool m_attribute { false }; }; } diff --git a/Userland/Libraries/LibWeb/DOM/EventTarget.h b/Userland/Libraries/LibWeb/DOM/EventTarget.h index f03d4a4fb2..af1a1d7b0c 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.h +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.h @@ -61,6 +61,7 @@ public: NonnullRefPtr<EventListener> listener; }; + Vector<EventListenerRegistration>& listeners() { return m_listeners; } const Vector<EventListenerRegistration>& listeners() const { return m_listeners; } Function<void(const Event&)> activation_behaviour; diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 7e8ca5b9da..32ed362c1f 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -62,6 +62,7 @@ enum class QuirksMode; namespace Web::HTML { class CanvasRenderingContext2D; +class EventHandler; class HTMLAnchorElement; class HTMLAreaElement; class HTMLAudioElement; diff --git a/Userland/Libraries/LibWeb/HTML/EventHandler.h b/Userland/Libraries/LibWeb/HTML/EventHandler.h new file mode 100644 index 0000000000..1a6229a2ae --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/EventHandler.h @@ -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; +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.cpp b/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.cpp new file mode 100644 index 0000000000..46585e80d9 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.cpp @@ -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 {}; +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h b/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h index 7cf05ecf4e..cb272d249b 100644 --- a/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h +++ b/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h @@ -26,6 +26,9 @@ #pragma once +#include <AK/Forward.h> +#include <LibWeb/Forward.h> + #define ENUMERATE_GLOBAL_EVENT_HANDLERS(E) \ E(onabort, HTML::EventNames::abort) \ E(onauxclick, "auxclick") \ @@ -93,3 +96,25 @@ E(onwebkitanimationstart, "webkitanimationstart") \ E(onwebkittransitionend, "webkittransitionend") \ 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; +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp index e6b7272f8d..4e3277f396 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp @@ -27,6 +27,7 @@ #include <LibWeb/CSS/StyleProperties.h> #include <LibWeb/CSS/StyleValue.h> #include <LibWeb/DOM/Document.h> +#include <LibWeb/DOM/Window.h> #include <LibWeb/HTML/HTMLBodyElement.h> 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(); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h b/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h index d8d41cbb7b..e5e169621a 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h @@ -41,6 +41,9 @@ public: virtual void apply_presentational_hints(CSS::StyleProperties&) const override; private: + // ^HTML::GlobalEventHandlers + virtual EventTarget& global_event_handlers_to_event_target() override; + RefPtr<CSS::ImageStyleValue> m_background_style_value; }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp index eb5356a594..ac09cb1d7a 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -25,11 +25,17 @@ */ #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/EventListener.h> +#include <LibWeb/HTML/EventHandler.h> #include <LibWeb/HTML/HTMLAnchorElement.h> #include <LibWeb/HTML/HTMLElement.h> #include <LibWeb/Layout/BreakNode.h> #include <LibWeb/Layout/TextNode.h> +#include <LibWeb/UIEvents/EventNames.h> namespace Web::HTML { @@ -138,4 +144,17 @@ bool HTMLElement::cannot_navigate() const 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 +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.h b/Userland/Libraries/LibWeb/HTML/HTMLElement.h index ee602a62b5..b070c13e49 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.h @@ -27,10 +27,14 @@ #pragma once #include <LibWeb/DOM/Element.h> +#include <LibWeb/HTML/EventNames.h> +#include <LibWeb/HTML/GlobalEventHandlers.h> namespace Web::HTML { -class HTMLElement : public DOM::Element { +class HTMLElement + : public DOM::Element + , public HTML::GlobalEventHandlers { public: using WrapperType = Bindings::HTMLElementWrapper; @@ -48,7 +52,13 @@ public: bool cannot_navigate() const; +protected: + virtual void parse_attribute(const FlyString& name, const String& value) override; + private: + // ^HTML::GlobalEventHandlers + virtual EventTarget& global_event_handlers_to_event_target() override { return *this; } + enum class ContentEditableState { True, False, diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.idl b/Userland/Libraries/LibWeb/HTML/HTMLElement.idl index 6b5de34cdb..5369c9a3cd 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLElement.idl +++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.idl @@ -8,4 +8,76 @@ interface HTMLElement : Element { attribute DOMString contentEditable; [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; + }; |