diff --git a/src/browser/Page.zig b/src/browser/Page.zig
index f22084a3..4c6b6ea8 100644
--- a/src/browser/Page.zig
+++ b/src/browser/Page.zig
@@ -102,6 +102,20 @@ _element_shadow_roots: Element.ShadowRootLookup = .{},
_node_owner_documents: Node.OwnerDocumentLookup = .{},
_element_assigned_slots: Element.AssignedSlotLookup = .{},
+/// Lazily-created inline event listeners (or listeners provided as attributes).
+/// Avoids bloating all elements with extra function fields for rare usage.
+///
+/// Use this when a listener provided like these:
+///
+/// ```html
+///
+/// ```
+///
+/// ```js
+/// img.onload = () => { ... };
+/// ```
+_element_attr_listeners: Element.AttrListenerLookup = .{},
+
_script_manager: ScriptManager,
// List of active MutationObservers
@@ -316,6 +330,9 @@ fn reset(self: *Page, comptime initializing: bool) !void {
self._element_shadow_roots = .{};
self._node_owner_documents = .{};
self._element_assigned_slots = .{};
+
+ self._element_attr_listeners = .{};
+
self._notified_network_idle = .init;
self._notified_network_almost_idle = .init;
@@ -1150,6 +1167,35 @@ pub fn getElementByIdFromNode(self: *Page, node: *Node, id: []const u8) ?*Elemen
return null;
}
+/// Sets an inline event listener (`onload`, `onclick`, `onwheel` etc.);
+/// overrides the listener if there's already one.
+pub fn setAttrListener(
+ self: *Page,
+ element: *Element,
+ listener_type: Element.KnownListener,
+ listener_callback: JS.Function.Global,
+) !void {
+ if (comptime IS_DEBUG) {
+ log.debug(.event, "Page.setAttrListener", .{
+ .element = element,
+ .listener_type = listener_type,
+ });
+ }
+
+ const key = element.calcAttrListenerKey(listener_type);
+ const gop = try self._element_attr_listeners.getOrPut(self.arena, key);
+ gop.value_ptr.* = listener_callback;
+}
+
+/// Returns the inline event listener by an element and listener type.
+pub fn getAttrListener(
+ self: *const Page,
+ element: *Element,
+ listener_type: Element.KnownListener,
+) ?JS.Function.Global {
+ return self._element_attr_listeners.get(element.calcAttrListenerKey(listener_type));
+}
+
pub fn registerPerformanceObserver(self: *Page, observer: *PerformanceObserver) !void {
return self._performance_observers.append(self.arena, observer);
}
@@ -2189,6 +2235,236 @@ fn populateElementAttributes(self: *Page, element: *Element, list: anytype) !voi
}
var attributes = try element.createAttributeList(self);
while (list.next()) |attr| {
+ // Event handlers can be provided like attributes; here we check if there's such.
+ const name = attr.name.local;
+ lp.assert(name.len != 0, "populateElementAttributes: 0-length attr name", .{ .attr = attr });
+ // Idea here is to make this check as cheap as possible.
+ const has_on_prefix = @as(u16, @bitCast([2]u8{ name.ptr[0], name.ptr[1 % name.len] })) == asUint("on");
+ // We may have found an event handler.
+ if (has_on_prefix) {
+ // Must be usable as function.
+ const func = try self.js.stringToPersistedFunction(attr.value.slice());
+
+ // Longest known listener kind is 32 bytes long.
+ const remaining: u6 = @truncate(name.len -| 2);
+ const unsafe = name.ptr + 2;
+ const Vec16x8 = @Vector(16, u8);
+ const Vec32x8 = @Vector(32, u8);
+
+ switch (remaining) {
+ 3 => if (@as(u24, @bitCast(unsafe[0..3].*)) == asUint("cut")) {
+ try self.setAttrListener(element, .cut, func);
+ },
+ 4 => switch (@as(u32, @bitCast(unsafe[0..4].*))) {
+ asUint("blur") => try self.setAttrListener(element, .blur, func),
+ asUint("copy") => try self.setAttrListener(element, .copy, func),
+ asUint("drag") => try self.setAttrListener(element, .drag, func),
+ asUint("drop") => try self.setAttrListener(element, .drop, func),
+ asUint("load") => try self.setAttrListener(element, .load, func),
+ asUint("play") => try self.setAttrListener(element, .play, func),
+ else => {},
+ },
+ 5 => switch (@as(u40, @bitCast(unsafe[0..5].*))) {
+ asUint("abort") => try self.setAttrListener(element, .abort, func),
+ asUint("click") => try self.setAttrListener(element, .click, func),
+ asUint("close") => try self.setAttrListener(element, .close, func),
+ asUint("ended") => try self.setAttrListener(element, .ended, func),
+ asUint("error") => try self.setAttrListener(element, .@"error", func),
+ asUint("focus") => try self.setAttrListener(element, .focus, func),
+ asUint("input") => try self.setAttrListener(element, .input, func),
+ asUint("keyup") => try self.setAttrListener(element, .keyup, func),
+ asUint("paste") => try self.setAttrListener(element, .paste, func),
+ asUint("pause") => try self.setAttrListener(element, .pause, func),
+ asUint("reset") => try self.setAttrListener(element, .reset, func),
+ asUint("wheel") => try self.setAttrListener(element, .wheel, func),
+ else => {},
+ },
+ 6 => switch (@as(u48, @bitCast(unsafe[0..6].*))) {
+ asUint("cancel") => try self.setAttrListener(element, .cancel, func),
+ asUint("change") => try self.setAttrListener(element, .change, func),
+ asUint("resize") => try self.setAttrListener(element, .resize, func),
+ asUint("scroll") => try self.setAttrListener(element, .scroll, func),
+ asUint("seeked") => try self.setAttrListener(element, .seeked, func),
+ asUint("select") => try self.setAttrListener(element, .select, func),
+ asUint("submit") => try self.setAttrListener(element, .submit, func),
+ asUint("toggle") => try self.setAttrListener(element, .toggle, func),
+ else => {},
+ },
+ 7 => switch (@as(u56, @bitCast(unsafe[0..7].*))) {
+ asUint("canplay") => try self.setAttrListener(element, .canplay, func),
+ asUint("command") => try self.setAttrListener(element, .command, func),
+ asUint("dragend") => try self.setAttrListener(element, .dragend, func),
+ asUint("emptied") => try self.setAttrListener(element, .emptied, func),
+ asUint("invalid") => try self.setAttrListener(element, .invalid, func),
+ asUint("keydown") => try self.setAttrListener(element, .keydown, func),
+ asUint("mouseup") => try self.setAttrListener(element, .mouseup, func),
+ asUint("playing") => try self.setAttrListener(element, .playing, func),
+ asUint("seeking") => try self.setAttrListener(element, .seeking, func),
+ asUint("stalled") => try self.setAttrListener(element, .stalled, func),
+ asUint("suspend") => try self.setAttrListener(element, .@"suspend", func),
+ asUint("waiting") => try self.setAttrListener(element, .waiting, func),
+ else => {},
+ },
+ 8 => switch (@as(u64, @bitCast(unsafe[0..8].*))) {
+ asUint("auxclick") => try self.setAttrListener(element, .auxclick, func),
+ asUint("dblclick") => try self.setAttrListener(element, .dblclick, func),
+ asUint("dragexit") => try self.setAttrListener(element, .dragexit, func),
+ asUint("dragover") => try self.setAttrListener(element, .dragover, func),
+ asUint("formdata") => try self.setAttrListener(element, .formdata, func),
+ asUint("keypress") => try self.setAttrListener(element, .keypress, func),
+ asUint("mouseout") => try self.setAttrListener(element, .mouseout, func),
+ asUint("progress") => try self.setAttrListener(element, .progress, func),
+ else => {},
+ },
+ // Won't fit to 64-bit integer; we do 2 checks.
+ 9 => switch (@as(u64, @bitCast(unsafe[0..8].*))) {
+ asUint("cuechang") => if (unsafe[8] == 'e') try self.setAttrListener(element, .cuechange, func),
+ asUint("dragente") => if (unsafe[8] == 'r') try self.setAttrListener(element, .dragenter, func),
+ asUint("dragleav") => if (unsafe[8] == 'e') try self.setAttrListener(element, .dragleave, func),
+ asUint("dragstar") => if (unsafe[8] == 't') try self.setAttrListener(element, .dragstart, func),
+ asUint("loadstar") => if (unsafe[8] == 't') try self.setAttrListener(element, .loadstart, func),
+ asUint("mousedow") => if (unsafe[8] == 'n') try self.setAttrListener(element, .mousedown, func),
+ asUint("mousemov") => if (unsafe[8] == 'e') try self.setAttrListener(element, .mousemove, func),
+ asUint("mouseove") => if (unsafe[8] == 'r') try self.setAttrListener(element, .mouseover, func),
+ asUint("pointeru") => if (unsafe[8] == 'p') try self.setAttrListener(element, .pointerup, func),
+ asUint("scrollen") => if (unsafe[8] == 'd') try self.setAttrListener(element, .scrollend, func),
+ else => {},
+ },
+ 10 => switch (@as(u64, @bitCast(unsafe[0..8].*))) {
+ asUint("loadedda") => if (asUint("ta") == @as(u16, @bitCast(unsafe[8..10].*)))
+ try self.setAttrListener(element, .loadeddata, func),
+ asUint("pointero") => if (asUint("ut") == @as(u16, @bitCast(unsafe[8..10].*)))
+ try self.setAttrListener(element, .pointerout, func),
+ asUint("ratechan") => if (asUint("ge") == @as(u16, @bitCast(unsafe[8..10].*)))
+ try self.setAttrListener(element, .ratechange, func),
+ asUint("slotchan") => if (asUint("ge") == @as(u16, @bitCast(unsafe[8..10].*)))
+ try self.setAttrListener(element, .slotchange, func),
+ asUint("timeupda") => if (asUint("te") == @as(u16, @bitCast(unsafe[8..10].*)))
+ try self.setAttrListener(element, .timeupdate, func),
+ else => {},
+ },
+ 11 => switch (@as(u64, @bitCast(unsafe[0..8].*))) {
+ asUint("beforein") => if (asUint("put") == @as(u24, @bitCast(unsafe[8..11].*)))
+ try self.setAttrListener(element, .beforeinput, func),
+ asUint("beforema") => if (asUint("tch") == @as(u24, @bitCast(unsafe[8..11].*)))
+ try self.setAttrListener(element, .beforematch, func),
+ asUint("contextl") => if (asUint("ost") == @as(u24, @bitCast(unsafe[8..11].*)))
+ try self.setAttrListener(element, .contextlost, func),
+ asUint("contextm") => if (asUint("enu") == @as(u24, @bitCast(unsafe[8..11].*)))
+ try self.setAttrListener(element, .contextmenu, func),
+ asUint("pointerd") => if (asUint("own") == @as(u24, @bitCast(unsafe[8..11].*)))
+ try self.setAttrListener(element, .pointerdown, func),
+ asUint("pointerm") => if (asUint("ove") == @as(u24, @bitCast(unsafe[8..11].*)))
+ try self.setAttrListener(element, .pointermove, func),
+ asUint("pointero") => if (asUint("ver") == @as(u24, @bitCast(unsafe[8..11].*)))
+ try self.setAttrListener(element, .pointerover, func),
+ asUint("selectst") => if (asUint("art") == @as(u24, @bitCast(unsafe[8..11].*)))
+ try self.setAttrListener(element, .selectstart, func),
+ else => {},
+ },
+ 12 => switch (@as(u64, @bitCast(unsafe[0..8].*))) {
+ asUint("animatio") => if (asUint("nend") == @as(u32, @bitCast(unsafe[8..12].*)))
+ try self.setAttrListener(element, .animationend, func),
+ asUint("beforeto") => if (asUint("ggle") == @as(u32, @bitCast(unsafe[8..12].*)))
+ try self.setAttrListener(element, .beforetoggle, func),
+ asUint("pointere") => if (asUint("nter") == @as(u32, @bitCast(unsafe[8..12].*)))
+ try self.setAttrListener(element, .pointerenter, func),
+ asUint("pointerl") => if (asUint("eave") == @as(u32, @bitCast(unsafe[8..12].*)))
+ try self.setAttrListener(element, .pointerleave, func),
+ asUint("volumech") => if (asUint("ange") == @as(u32, @bitCast(unsafe[8..12].*)))
+ try self.setAttrListener(element, .volumechange, func),
+ else => {},
+ },
+ 13 => switch (@as(u64, @bitCast(unsafe[0..8].*))) {
+ asUint("pointerc") => if (asUint("ancel") == @as(u40, @bitCast(unsafe[8..13].*)))
+ try self.setAttrListener(element, .pointercancel, func),
+ asUint("transiti") => switch (@as(u40, @bitCast(unsafe[8..13].*))) {
+ asUint("onend") => try self.setAttrListener(element, .transitionend, func),
+ asUint("onrun") => try self.setAttrListener(element, .transitionrun, func),
+ else => {},
+ },
+ else => {},
+ },
+ 14 => switch (@as(u64, @bitCast(unsafe[0..8].*))) {
+ asUint("animatio") => if (asUint("nstart") == @as(u48, @bitCast(unsafe[8..14].*)))
+ try self.setAttrListener(element, .animationstart, func),
+ asUint("canplayt") => if (asUint("hrough") == @as(u48, @bitCast(unsafe[8..14].*)))
+ try self.setAttrListener(element, .canplaythrough, func),
+ asUint("duration") => if (asUint("change") == @as(u48, @bitCast(unsafe[8..14].*)))
+ try self.setAttrListener(element, .durationchange, func),
+ asUint("loadedme") => if (asUint("tadata") == @as(u48, @bitCast(unsafe[8..14].*)))
+ try self.setAttrListener(element, .loadedmetadata, func),
+ else => {},
+ },
+ 15 => switch (@as(u64, @bitCast(unsafe[0..8].*))) {
+ asUint("animatio") => if (asUint("ncancel") == @as(u56, @bitCast(unsafe[8..15].*)))
+ try self.setAttrListener(element, .animationcancel, func),
+ asUint("contextr") => if (asUint("estored") == @as(u56, @bitCast(unsafe[8..15].*)))
+ try self.setAttrListener(element, .contextrestored, func),
+ asUint("fullscre") => if (asUint("enerror") == @as(u56, @bitCast(unsafe[8..15].*)))
+ try self.setAttrListener(element, .fullscreenerror, func),
+ asUint("selectio") => if (asUint("nchange") == @as(u56, @bitCast(unsafe[8..15].*)))
+ try self.setAttrListener(element, .selectionchange, func),
+ asUint("transiti") => if (asUint("onstart") == @as(u56, @bitCast(unsafe[8..15].*)))
+ try self.setAttrListener(element, .transitionstart, func),
+ else => {},
+ },
+ // Can't switch on vector types.
+ 16 => {
+ const as_vector: Vec16x8 = unsafe[0..16].*;
+
+ if (@reduce(.And, as_vector == @as(Vec16x8, "fullscreenchange".*))) {
+ try self.setAttrListener(element, .fullscreenchange, func);
+ } else if (@reduce(.And, as_vector == @as(Vec16x8, "pointerrawupdate".*))) {
+ try self.setAttrListener(element, .pointerrawupdate, func);
+ } else if (@reduce(.And, as_vector == @as(Vec16x8, "transitioncancel".*))) {
+ try self.setAttrListener(element, .transitioncancel, func);
+ }
+ },
+ 17 => {
+ const as_vector: Vec16x8 = unsafe[0..16].*;
+
+ const dirty = @reduce(.And, as_vector == @as(Vec16x8, "gotpointercaptur".*)) and
+ unsafe[16] == 'e';
+ if (dirty) {
+ try self.setAttrListener(element, .gotpointercapture, func);
+ }
+ },
+ 18 => {
+ const as_vector: Vec16x8 = unsafe[0..16].*;
+
+ const is_animationiteration = @reduce(.And, as_vector == @as(Vec16x8, "animationiterati".*)) and
+ asUint("on") == @as(u16, @bitCast(unsafe[16..18].*));
+ if (is_animationiteration) {
+ try self.setAttrListener(element, .animationiteration, func);
+ } else {
+ const is_lostpointercapture = @reduce(.And, as_vector == @as(Vec16x8, "lostpointercaptu".*)) and
+ asUint("re") == @as(u16, @bitCast(unsafe[16..18].*));
+ if (is_lostpointercapture) {
+ try self.setAttrListener(element, .lostpointercapture, func);
+ }
+ }
+ },
+ 23 => {
+ const as_vector: Vec16x8 = unsafe[0..16].*;
+
+ const dirty = @reduce(.And, as_vector == @as(Vec16x8, "securitypolicyvi".*)) and
+ asUint("olation") == @as(u56, @bitCast(unsafe[16..23].*));
+ if (dirty) {
+ try self.setAttrListener(element, .securitypolicyviolation, func);
+ }
+ },
+ 32 => {
+ const as_vector: Vec32x8 = unsafe[0..32].*;
+
+ if (@reduce(.And, as_vector == @as(Vec32x8, "contentvisibilityautostatechange".*))) {
+ try self.setAttrListener(element, .contentvisibilityautostatechange, func);
+ }
+ },
+ else => {},
+ }
+ }
+
try attributes.putNew(attr.name.local.slice(), attr.value.slice(), self);
}
}
diff --git a/src/browser/tests/element/html/event_listeners.html b/src/browser/tests/element/html/event_listeners.html
new file mode 100644
index 00000000..9e7f9ebd
--- /dev/null
+++ b/src/browser/tests/element/html/event_listeners.html
@@ -0,0 +1,490 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/browser/webapi/Element.zig b/src/browser/webapi/Element.zig
index f983b514..619d95cd 100644
--- a/src/browser/webapi/Element.zig
+++ b/src/browser/webapi/Element.zig
@@ -49,6 +49,129 @@ pub const RelListLookup = std.AutoHashMapUnmanaged(*Element, *collections.DOMTok
pub const ShadowRootLookup = std.AutoHashMapUnmanaged(*Element, *ShadowRoot);
pub const AssignedSlotLookup = std.AutoHashMapUnmanaged(*Element, *Html.Slot);
+/// Better to discriminate it since not directly a pointer int.
+///
+/// See `calcAttrListenerKey` to obtain one.
+const AttrListenerKey = u64;
+/// Use `getAttrListenerKey` to create a key.
+pub const AttrListenerLookup = std.AutoHashMapUnmanaged(AttrListenerKey, js.Function.Global);
+
+/// Enum of known event listeners; increasing the size of it (u7)
+/// can cause `AttrListenerKey` to behave incorrectly.
+pub const KnownListener = enum(u7) {
+ abort,
+ animationcancel,
+ animationend,
+ animationiteration,
+ animationstart,
+ auxclick,
+ beforeinput,
+ beforematch,
+ beforetoggle,
+ blur,
+ cancel,
+ canplay,
+ canplaythrough,
+ change,
+ click,
+ close,
+ command,
+ contentvisibilityautostatechange,
+ contextlost,
+ contextmenu,
+ contextrestored,
+ copy,
+ cuechange,
+ cut,
+ dblclick,
+ drag,
+ dragend,
+ dragenter,
+ dragexit,
+ dragleave,
+ dragover,
+ dragstart,
+ drop,
+ durationchange,
+ emptied,
+ ended,
+ @"error",
+ focus,
+ formdata,
+ fullscreenchange,
+ fullscreenerror,
+ gotpointercapture,
+ input,
+ invalid,
+ keydown,
+ keypress,
+ keyup,
+ load,
+ loadeddata,
+ loadedmetadata,
+ loadstart,
+ lostpointercapture,
+ mousedown,
+ mousemove,
+ mouseout,
+ mouseover,
+ mouseup,
+ paste,
+ pause,
+ play,
+ playing,
+ pointercancel,
+ pointerdown,
+ pointerenter,
+ pointerleave,
+ pointermove,
+ pointerout,
+ pointerover,
+ pointerrawupdate,
+ pointerup,
+ progress,
+ ratechange,
+ reset,
+ resize,
+ scroll,
+ scrollend,
+ securitypolicyviolation,
+ seeked,
+ seeking,
+ select,
+ selectionchange,
+ selectstart,
+ slotchange,
+ stalled,
+ submit,
+ @"suspend",
+ timeupdate,
+ toggle,
+ transitioncancel,
+ transitionend,
+ transitionrun,
+ transitionstart,
+ volumechange,
+ waiting,
+ wheel,
+};
+
+/// Calculates a lookup key (`AttrListenerKey`) to use with `AttrListenerLookup` for an element.
+/// NEVER use generated key to retrieve a pointer back. Portability is not guaranteed.
+pub fn calcAttrListenerKey(self: *Element, event_type: KnownListener) AttrListenerKey {
+ // We can use `Element` for the key too; `EventTarget` is strict about
+ // its size and alignment, though.
+ const target = self.asEventTarget();
+ // Check if we have 3 bits available from alignment of 8.
+ lp.assert(@alignOf(@TypeOf(target)) == 8, "createLookupKey: incorrect alignment", .{
+ .event_target_alignment = @alignOf(@TypeOf(target)),
+ });
+
+ const ptr = @intFromPtr(target) >> 3;
+ lp.assert(ptr < (1 << 57), "createLookupKey: pointer overflow", .{ .ptr = ptr });
+ return ptr | (@as(u64, @intFromEnum(event_type)) << 57);
+}
+
pub const Namespace = enum(u8) {
html,
svg,
diff --git a/src/browser/webapi/element/Html.zig b/src/browser/webapi/element/Html.zig
index c96c25cb..639231b5 100644
--- a/src/browser/webapi/element/Html.zig
+++ b/src/browser/webapi/element/Html.zig
@@ -333,6 +333,766 @@ pub fn click(self: *HtmlElement, page: *Page) !void {
try page._event_manager.dispatch(self.asEventTarget(), event.asEvent());
}
+pub fn setOnAbort(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .abort, callback);
+}
+
+pub fn getOnAbort(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .abort);
+}
+
+pub fn setOnAnimationCancel(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .animationcancel, callback);
+}
+
+pub fn getOnAnimationCancel(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .animationcancel);
+}
+
+pub fn setOnAnimationEnd(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .animationend, callback);
+}
+
+pub fn getOnAnimationEnd(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .animationend);
+}
+
+pub fn setOnAnimationIteration(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .animationiteration, callback);
+}
+
+pub fn getOnAnimationIteration(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .animationiteration);
+}
+
+pub fn setOnAnimationStart(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .animationstart, callback);
+}
+
+pub fn getOnAnimationStart(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .animationstart);
+}
+
+pub fn setOnAuxClick(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .auxclick, callback);
+}
+
+pub fn getOnAuxClick(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .auxclick);
+}
+
+pub fn setOnBeforeInput(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .beforeinput, callback);
+}
+
+pub fn getOnBeforeInput(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .beforeinput);
+}
+
+pub fn setOnBeforeMatch(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .beforematch, callback);
+}
+
+pub fn getOnBeforeMatch(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .beforematch);
+}
+
+pub fn setOnBeforeToggle(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .beforetoggle, callback);
+}
+
+pub fn getOnBeforeToggle(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .beforetoggle);
+}
+
+pub fn setOnBlur(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .blur, callback);
+}
+
+pub fn getOnBlur(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .blur);
+}
+
+pub fn setOnCancel(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .cancel, callback);
+}
+
+pub fn getOnCancel(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .cancel);
+}
+
+pub fn setOnCanPlay(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .canplay, callback);
+}
+
+pub fn getOnCanPlay(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .canplay);
+}
+
+pub fn setOnCanPlayThrough(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .canplaythrough, callback);
+}
+
+pub fn getOnCanPlayThrough(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .canplaythrough);
+}
+
+pub fn setOnChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .change, callback);
+}
+
+pub fn getOnChange(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .change);
+}
+
+pub fn setOnClick(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .click, callback);
+}
+
+pub fn getOnClick(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .click);
+}
+
+pub fn setOnClose(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .close, callback);
+}
+
+pub fn getOnClose(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .close);
+}
+
+pub fn setOnCommand(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .command, callback);
+}
+
+pub fn getOnCommand(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .command);
+}
+
+pub fn setOnContentVisibilityAutoStateChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .contentvisibilityautostatechange, callback);
+}
+
+pub fn getOnContentVisibilityAutoStateChange(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .contentvisibilityautostatechange);
+}
+
+pub fn setOnContextLost(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .contextlost, callback);
+}
+
+pub fn getOnContextLost(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .contextlost);
+}
+
+pub fn setOnContextMenu(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .contextmenu, callback);
+}
+
+pub fn getOnContextMenu(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .contextmenu);
+}
+
+pub fn setOnContextRestored(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .contextrestored, callback);
+}
+
+pub fn getOnContextRestored(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .contextrestored);
+}
+
+pub fn setOnCopy(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .copy, callback);
+}
+
+pub fn getOnCopy(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .copy);
+}
+
+pub fn setOnCueChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .cuechange, callback);
+}
+
+pub fn getOnCueChange(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .cuechange);
+}
+
+pub fn setOnCut(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .cut, callback);
+}
+
+pub fn getOnCut(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .cut);
+}
+
+pub fn setOnDblClick(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .dblclick, callback);
+}
+
+pub fn getOnDblClick(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .dblclick);
+}
+
+pub fn setOnDrag(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .drag, callback);
+}
+
+pub fn getOnDrag(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .drag);
+}
+
+pub fn setOnDragEnd(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .dragend, callback);
+}
+
+pub fn getOnDragEnd(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .dragend);
+}
+
+pub fn setOnDragEnter(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .dragenter, callback);
+}
+
+pub fn getOnDragEnter(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .dragenter);
+}
+
+pub fn setOnDragExit(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .dragexit, callback);
+}
+
+pub fn getOnDragExit(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .dragexit);
+}
+
+pub fn setOnDragLeave(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .dragleave, callback);
+}
+
+pub fn getOnDragLeave(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .dragleave);
+}
+
+pub fn setOnDragOver(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .dragover, callback);
+}
+
+pub fn getOnDragOver(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .dragover);
+}
+
+pub fn setOnDragStart(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .dragstart, callback);
+}
+
+pub fn getOnDragStart(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .dragstart);
+}
+
+pub fn setOnDrop(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .drop, callback);
+}
+
+pub fn getOnDrop(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .drop);
+}
+
+pub fn setOnDurationChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .durationchange, callback);
+}
+
+pub fn getOnDurationChange(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .durationchange);
+}
+
+pub fn setOnEmptied(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .emptied, callback);
+}
+
+pub fn getOnEmptied(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .emptied);
+}
+
+pub fn setOnEnded(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .ended, callback);
+}
+
+pub fn getOnEnded(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .ended);
+}
+
+pub fn setOnError(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .@"error", callback);
+}
+
+pub fn getOnError(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .@"error");
+}
+
+pub fn setOnFocus(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .focus, callback);
+}
+
+pub fn getOnFocus(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .focus);
+}
+
+pub fn setOnFormData(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .formdata, callback);
+}
+
+pub fn getOnFormData(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .formdata);
+}
+
+pub fn setOnFullscreenChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .fullscreenchange, callback);
+}
+
+pub fn getOnFullscreenChange(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .fullscreenchange);
+}
+
+pub fn setOnFullscreenError(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .fullscreenerror, callback);
+}
+
+pub fn getOnFullscreenError(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .fullscreenerror);
+}
+
+pub fn setOnGotPointerCapture(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .gotpointercapture, callback);
+}
+
+pub fn getOnGotPointerCapture(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .gotpointercapture);
+}
+
+pub fn setOnInput(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .input, callback);
+}
+
+pub fn getOnInput(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .input);
+}
+
+pub fn setOnInvalid(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .invalid, callback);
+}
+
+pub fn getOnInvalid(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .invalid);
+}
+
+pub fn setOnKeyDown(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .keydown, callback);
+}
+
+pub fn getOnKeyDown(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .keydown);
+}
+
+pub fn setOnKeyPress(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .keypress, callback);
+}
+
+pub fn getOnKeyPress(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .keypress);
+}
+
+pub fn setOnKeyUp(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .keyup, callback);
+}
+
+pub fn getOnKeyUp(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .keyup);
+}
+
+pub fn setOnLoad(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .load, callback);
+}
+
+pub fn getOnLoad(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .load);
+}
+
+pub fn setOnLoadedData(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .loadeddata, callback);
+}
+
+pub fn getOnLoadedData(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .loadeddata);
+}
+
+pub fn setOnLoadedMetadata(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .loadedmetadata, callback);
+}
+
+pub fn getOnLoadedMetadata(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .loadedmetadata);
+}
+
+pub fn setOnLoadStart(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .loadstart, callback);
+}
+
+pub fn getOnLoadStart(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .loadstart);
+}
+
+pub fn setOnLostPointerCapture(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .lostpointercapture, callback);
+}
+
+pub fn getOnLostPointerCapture(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .lostpointercapture);
+}
+
+pub fn setOnMouseDown(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .mousedown, callback);
+}
+
+pub fn getOnMouseDown(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .mousedown);
+}
+
+pub fn setOnMouseMove(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .mousemove, callback);
+}
+
+pub fn getOnMouseMove(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .mousemove);
+}
+
+pub fn setOnMouseOut(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .mouseout, callback);
+}
+
+pub fn getOnMouseOut(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .mouseout);
+}
+
+pub fn setOnMouseOver(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .mouseover, callback);
+}
+
+pub fn getOnMouseOver(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .mouseover);
+}
+
+pub fn setOnMouseUp(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .mouseup, callback);
+}
+
+pub fn getOnMouseUp(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .mouseup);
+}
+
+pub fn setOnPaste(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .paste, callback);
+}
+
+pub fn getOnPaste(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .paste);
+}
+
+pub fn setOnPause(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .pause, callback);
+}
+
+pub fn getOnPause(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .pause);
+}
+
+pub fn setOnPlay(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .play, callback);
+}
+
+pub fn getOnPlay(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .play);
+}
+
+pub fn setOnPlaying(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .playing, callback);
+}
+
+pub fn getOnPlaying(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .playing);
+}
+
+pub fn setOnPointerCancel(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .pointercancel, callback);
+}
+
+pub fn getOnPointerCancel(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .pointercancel);
+}
+
+pub fn setOnPointerDown(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .pointerdown, callback);
+}
+
+pub fn getOnPointerDown(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .pointerdown);
+}
+
+pub fn setOnPointerEnter(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .pointerenter, callback);
+}
+
+pub fn getOnPointerEnter(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .pointerenter);
+}
+
+pub fn setOnPointerLeave(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .pointerleave, callback);
+}
+
+pub fn getOnPointerLeave(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .pointerleave);
+}
+
+pub fn setOnPointerMove(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .pointermove, callback);
+}
+
+pub fn getOnPointerMove(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .pointermove);
+}
+
+pub fn setOnPointerOut(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .pointerout, callback);
+}
+
+pub fn getOnPointerOut(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .pointerout);
+}
+
+pub fn setOnPointerOver(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .pointerover, callback);
+}
+
+pub fn getOnPointerOver(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .pointerover);
+}
+
+pub fn setOnPointerRawUpdate(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .pointerrawupdate, callback);
+}
+
+pub fn getOnPointerRawUpdate(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .pointerrawupdate);
+}
+
+pub fn setOnPointerUp(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .pointerup, callback);
+}
+
+pub fn getOnPointerUp(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .pointerup);
+}
+
+pub fn setOnProgress(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .progress, callback);
+}
+
+pub fn getOnProgress(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .progress);
+}
+
+pub fn setOnRateChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .ratechange, callback);
+}
+
+pub fn getOnRateChange(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .ratechange);
+}
+
+pub fn setOnReset(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .reset, callback);
+}
+
+pub fn getOnReset(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .reset);
+}
+
+pub fn setOnResize(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .resize, callback);
+}
+
+pub fn getOnResize(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .resize);
+}
+
+pub fn setOnScroll(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .scroll, callback);
+}
+
+pub fn getOnScroll(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .scroll);
+}
+
+pub fn setOnScrollEnd(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .scrollend, callback);
+}
+
+pub fn getOnScrollEnd(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .scrollend);
+}
+
+pub fn setOnSecurityPolicyViolation(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .securitypolicyviolation, callback);
+}
+
+pub fn getOnSecurityPolicyViolation(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .securitypolicyviolation);
+}
+
+pub fn setOnSeeked(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .seeked, callback);
+}
+
+pub fn getOnSeeked(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .seeked);
+}
+
+pub fn setOnSeeking(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .seeking, callback);
+}
+
+pub fn getOnSeeking(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .seeking);
+}
+
+pub fn setOnSelect(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .select, callback);
+}
+
+pub fn getOnSelect(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .select);
+}
+
+pub fn setOnSelectionChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .selectionchange, callback);
+}
+
+pub fn getOnSelectionChange(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .selectionchange);
+}
+
+pub fn setOnSelectStart(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .selectstart, callback);
+}
+
+pub fn getOnSelectStart(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .selectstart);
+}
+
+pub fn setOnSlotChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .slotchange, callback);
+}
+
+pub fn getOnSlotChange(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .slotchange);
+}
+
+pub fn setOnStalled(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .stalled, callback);
+}
+
+pub fn getOnStalled(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .stalled);
+}
+
+pub fn setOnSubmit(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .submit, callback);
+}
+
+pub fn getOnSubmit(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .submit);
+}
+
+pub fn setOnSuspend(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .@"suspend", callback);
+}
+
+pub fn getOnSuspend(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .@"suspend");
+}
+
+pub fn setOnTimeUpdate(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .timeupdate, callback);
+}
+
+pub fn getOnTimeUpdate(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .timeupdate);
+}
+
+pub fn setOnToggle(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .toggle, callback);
+}
+
+pub fn getOnToggle(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .toggle);
+}
+
+pub fn setOnTransitionCancel(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .transitioncancel, callback);
+}
+
+pub fn getOnTransitionCancel(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .transitioncancel);
+}
+
+pub fn setOnTransitionEnd(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .transitionend, callback);
+}
+
+pub fn getOnTransitionEnd(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .transitionend);
+}
+
+pub fn setOnTransitionRun(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .transitionrun, callback);
+}
+
+pub fn getOnTransitionRun(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .transitionrun);
+}
+
+pub fn setOnTransitionStart(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .transitionstart, callback);
+}
+
+pub fn getOnTransitionStart(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .transitionstart);
+}
+
+pub fn setOnVolumeChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .volumechange, callback);
+}
+
+pub fn getOnVolumeChange(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .volumechange);
+}
+
+pub fn setOnWaiting(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .waiting, callback);
+}
+
+pub fn getOnWaiting(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .waiting);
+}
+
+pub fn setOnWheel(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void {
+ return page.setAttrListener(self.asElement(), .wheel, callback);
+}
+
+pub fn getOnWheel(self: *HtmlElement, page: *Page) ?js.Function.Global {
+ return page.getAttrListener(self.asElement(), .wheel);
+}
+
pub const JsApi = struct {
pub const bridge = js.Bridge(HtmlElement);
@@ -352,6 +1112,102 @@ pub const JsApi = struct {
}
pub const insertAdjacentHTML = bridge.function(HtmlElement.insertAdjacentHTML, .{ .dom_exception = true });
pub const click = bridge.function(HtmlElement.click, .{});
+
+ pub const onabort = bridge.accessor(HtmlElement.getOnAbort, HtmlElement.setOnAbort, .{});
+ pub const onanimationcancel = bridge.accessor(HtmlElement.getOnAnimationCancel, HtmlElement.setOnAnimationCancel, .{});
+ pub const onanimationend = bridge.accessor(HtmlElement.getOnAnimationEnd, HtmlElement.setOnAnimationEnd, .{});
+ pub const onanimationiteration = bridge.accessor(HtmlElement.getOnAnimationIteration, HtmlElement.setOnAnimationIteration, .{});
+ pub const onanimationstart = bridge.accessor(HtmlElement.getOnAnimationStart, HtmlElement.setOnAnimationStart, .{});
+ pub const onauxclick = bridge.accessor(HtmlElement.getOnAuxClick, HtmlElement.setOnAuxClick, .{});
+ pub const onbeforeinput = bridge.accessor(HtmlElement.getOnBeforeInput, HtmlElement.setOnBeforeInput, .{});
+ pub const onbeforematch = bridge.accessor(HtmlElement.getOnBeforeMatch, HtmlElement.setOnBeforeMatch, .{});
+ pub const onbeforetoggle = bridge.accessor(HtmlElement.getOnBeforeToggle, HtmlElement.setOnBeforeToggle, .{});
+ pub const onblur = bridge.accessor(HtmlElement.getOnBlur, HtmlElement.setOnBlur, .{});
+ pub const oncancel = bridge.accessor(HtmlElement.getOnCancel, HtmlElement.setOnCancel, .{});
+ pub const oncanplay = bridge.accessor(HtmlElement.getOnCanPlay, HtmlElement.setOnCanPlay, .{});
+ pub const oncanplaythrough = bridge.accessor(HtmlElement.getOnCanPlayThrough, HtmlElement.setOnCanPlayThrough, .{});
+ pub const onchange = bridge.accessor(HtmlElement.getOnChange, HtmlElement.setOnChange, .{});
+ pub const onclick = bridge.accessor(HtmlElement.getOnClick, HtmlElement.setOnClick, .{});
+ pub const onclose = bridge.accessor(HtmlElement.getOnClose, HtmlElement.setOnClose, .{});
+ pub const oncommand = bridge.accessor(HtmlElement.getOnCommand, HtmlElement.setOnCommand, .{});
+ pub const oncontentvisibilityautostatechange = bridge.accessor(HtmlElement.getOnContentVisibilityAutoStateChange, HtmlElement.setOnContentVisibilityAutoStateChange, .{});
+ pub const oncontextlost = bridge.accessor(HtmlElement.getOnContextLost, HtmlElement.setOnContextLost, .{});
+ pub const oncontextmenu = bridge.accessor(HtmlElement.getOnContextMenu, HtmlElement.setOnContextMenu, .{});
+ pub const oncontextrestored = bridge.accessor(HtmlElement.getOnContextRestored, HtmlElement.setOnContextRestored, .{});
+ pub const oncopy = bridge.accessor(HtmlElement.getOnCopy, HtmlElement.setOnCopy, .{});
+ pub const oncuechange = bridge.accessor(HtmlElement.getOnCueChange, HtmlElement.setOnCueChange, .{});
+ pub const oncut = bridge.accessor(HtmlElement.getOnCut, HtmlElement.setOnCut, .{});
+ pub const ondblclick = bridge.accessor(HtmlElement.getOnDblClick, HtmlElement.setOnDblClick, .{});
+ pub const ondrag = bridge.accessor(HtmlElement.getOnDrag, HtmlElement.setOnDrag, .{});
+ pub const ondragend = bridge.accessor(HtmlElement.getOnDragEnd, HtmlElement.setOnDragEnd, .{});
+ pub const ondragenter = bridge.accessor(HtmlElement.getOnDragEnter, HtmlElement.setOnDragEnter, .{});
+ pub const ondragexit = bridge.accessor(HtmlElement.getOnDragExit, HtmlElement.setOnDragExit, .{});
+ pub const ondragleave = bridge.accessor(HtmlElement.getOnDragLeave, HtmlElement.setOnDragLeave, .{});
+ pub const ondragover = bridge.accessor(HtmlElement.getOnDragOver, HtmlElement.setOnDragOver, .{});
+ pub const ondragstart = bridge.accessor(HtmlElement.getOnDragStart, HtmlElement.setOnDragStart, .{});
+ pub const ondrop = bridge.accessor(HtmlElement.getOnDrop, HtmlElement.setOnDrop, .{});
+ pub const ondurationchange = bridge.accessor(HtmlElement.getOnDurationChange, HtmlElement.setOnDurationChange, .{});
+ pub const onemptied = bridge.accessor(HtmlElement.getOnEmptied, HtmlElement.setOnEmptied, .{});
+ pub const onended = bridge.accessor(HtmlElement.getOnEnded, HtmlElement.setOnEnded, .{});
+ pub const onerror = bridge.accessor(HtmlElement.getOnError, HtmlElement.setOnError, .{});
+ pub const onfocus = bridge.accessor(HtmlElement.getOnFocus, HtmlElement.setOnFocus, .{});
+ pub const onformdata = bridge.accessor(HtmlElement.getOnFormData, HtmlElement.setOnFormData, .{});
+ pub const onfullscreenchange = bridge.accessor(HtmlElement.getOnFullscreenChange, HtmlElement.setOnFullscreenChange, .{});
+ pub const onfullscreenerror = bridge.accessor(HtmlElement.getOnFullscreenError, HtmlElement.setOnFullscreenError, .{});
+ pub const ongotpointercapture = bridge.accessor(HtmlElement.getOnGotPointerCapture, HtmlElement.setOnGotPointerCapture, .{});
+ pub const oninput = bridge.accessor(HtmlElement.getOnInput, HtmlElement.setOnInput, .{});
+ pub const oninvalid = bridge.accessor(HtmlElement.getOnInvalid, HtmlElement.setOnInvalid, .{});
+ pub const onkeydown = bridge.accessor(HtmlElement.getOnKeyDown, HtmlElement.setOnKeyDown, .{});
+ pub const onkeypress = bridge.accessor(HtmlElement.getOnKeyPress, HtmlElement.setOnKeyPress, .{});
+ pub const onkeyup = bridge.accessor(HtmlElement.getOnKeyUp, HtmlElement.setOnKeyUp, .{});
+ pub const onload = bridge.accessor(HtmlElement.getOnLoad, HtmlElement.setOnLoad, .{});
+ pub const onloadeddata = bridge.accessor(HtmlElement.getOnLoadedData, HtmlElement.setOnLoadedData, .{});
+ pub const onloadedmetadata = bridge.accessor(HtmlElement.getOnLoadedMetadata, HtmlElement.setOnLoadedMetadata, .{});
+ pub const onloadstart = bridge.accessor(HtmlElement.getOnLoadStart, HtmlElement.setOnLoadStart, .{});
+ pub const onlostpointercapture = bridge.accessor(HtmlElement.getOnLostPointerCapture, HtmlElement.setOnLostPointerCapture, .{});
+ pub const onmousedown = bridge.accessor(HtmlElement.getOnMouseDown, HtmlElement.setOnMouseDown, .{});
+ pub const onmousemove = bridge.accessor(HtmlElement.getOnMouseMove, HtmlElement.setOnMouseMove, .{});
+ pub const onmouseout = bridge.accessor(HtmlElement.getOnMouseOut, HtmlElement.setOnMouseOut, .{});
+ pub const onmouseover = bridge.accessor(HtmlElement.getOnMouseOver, HtmlElement.setOnMouseOver, .{});
+ pub const onmouseup = bridge.accessor(HtmlElement.getOnMouseUp, HtmlElement.setOnMouseUp, .{});
+ pub const onpaste = bridge.accessor(HtmlElement.getOnPaste, HtmlElement.setOnPaste, .{});
+ pub const onpause = bridge.accessor(HtmlElement.getOnPause, HtmlElement.setOnPause, .{});
+ pub const onplay = bridge.accessor(HtmlElement.getOnPlay, HtmlElement.setOnPlay, .{});
+ pub const onplaying = bridge.accessor(HtmlElement.getOnPlaying, HtmlElement.setOnPlaying, .{});
+ pub const onpointercancel = bridge.accessor(HtmlElement.getOnPointerCancel, HtmlElement.setOnPointerCancel, .{});
+ pub const onpointerdown = bridge.accessor(HtmlElement.getOnPointerDown, HtmlElement.setOnPointerDown, .{});
+ pub const onpointerenter = bridge.accessor(HtmlElement.getOnPointerEnter, HtmlElement.setOnPointerEnter, .{});
+ pub const onpointerleave = bridge.accessor(HtmlElement.getOnPointerLeave, HtmlElement.setOnPointerLeave, .{});
+ pub const onpointermove = bridge.accessor(HtmlElement.getOnPointerMove, HtmlElement.setOnPointerMove, .{});
+ pub const onpointerout = bridge.accessor(HtmlElement.getOnPointerOut, HtmlElement.setOnPointerOut, .{});
+ pub const onpointerover = bridge.accessor(HtmlElement.getOnPointerOver, HtmlElement.setOnPointerOver, .{});
+ pub const onpointerrawupdate = bridge.accessor(HtmlElement.getOnPointerRawUpdate, HtmlElement.setOnPointerRawUpdate, .{});
+ pub const onpointerup = bridge.accessor(HtmlElement.getOnPointerUp, HtmlElement.setOnPointerUp, .{});
+ pub const onprogress = bridge.accessor(HtmlElement.getOnProgress, HtmlElement.setOnProgress, .{});
+ pub const onratechange = bridge.accessor(HtmlElement.getOnRateChange, HtmlElement.setOnRateChange, .{});
+ pub const onreset = bridge.accessor(HtmlElement.getOnReset, HtmlElement.setOnReset, .{});
+ pub const onresize = bridge.accessor(HtmlElement.getOnResize, HtmlElement.setOnResize, .{});
+ pub const onscroll = bridge.accessor(HtmlElement.getOnScroll, HtmlElement.setOnScroll, .{});
+ pub const onscrollend = bridge.accessor(HtmlElement.getOnScrollEnd, HtmlElement.setOnScrollEnd, .{});
+ pub const onsecuritypolicyviolation = bridge.accessor(HtmlElement.getOnSecurityPolicyViolation, HtmlElement.setOnSecurityPolicyViolation, .{});
+ pub const onseeked = bridge.accessor(HtmlElement.getOnSeeked, HtmlElement.setOnSeeked, .{});
+ pub const onseeking = bridge.accessor(HtmlElement.getOnSeeking, HtmlElement.setOnSeeking, .{});
+ pub const onselect = bridge.accessor(HtmlElement.getOnSelect, HtmlElement.setOnSelect, .{});
+ pub const onselectionchange = bridge.accessor(HtmlElement.getOnSelectionChange, HtmlElement.setOnSelectionChange, .{});
+ pub const onselectstart = bridge.accessor(HtmlElement.getOnSelectStart, HtmlElement.setOnSelectStart, .{});
+ pub const onslotchange = bridge.accessor(HtmlElement.getOnSlotChange, HtmlElement.setOnSlotChange, .{});
+ pub const onstalled = bridge.accessor(HtmlElement.getOnStalled, HtmlElement.setOnStalled, .{});
+ pub const onsubmit = bridge.accessor(HtmlElement.getOnSubmit, HtmlElement.setOnSubmit, .{});
+ pub const onsuspend = bridge.accessor(HtmlElement.getOnSuspend, HtmlElement.setOnSuspend, .{});
+ pub const ontimeupdate = bridge.accessor(HtmlElement.getOnTimeUpdate, HtmlElement.setOnTimeUpdate, .{});
+ pub const ontoggle = bridge.accessor(HtmlElement.getOnToggle, HtmlElement.setOnToggle, .{});
+ pub const ontransitioncancel = bridge.accessor(HtmlElement.getOnTransitionCancel, HtmlElement.setOnTransitionCancel, .{});
+ pub const ontransitionend = bridge.accessor(HtmlElement.getOnTransitionEnd, HtmlElement.setOnTransitionEnd, .{});
+ pub const ontransitionrun = bridge.accessor(HtmlElement.getOnTransitionRun, HtmlElement.setOnTransitionRun, .{});
+ pub const ontransitionstart = bridge.accessor(HtmlElement.getOnTransitionStart, HtmlElement.setOnTransitionStart, .{});
+ pub const onvolumechange = bridge.accessor(HtmlElement.getOnVolumeChange, HtmlElement.setOnVolumeChange, .{});
+ pub const onwaiting = bridge.accessor(HtmlElement.getOnWaiting, HtmlElement.setOnWaiting, .{});
+ pub const onwheel = bridge.accessor(HtmlElement.getOnWheel, HtmlElement.setOnWheel, .{});
};
pub const Build = struct {
@@ -382,3 +1238,8 @@ pub const Build = struct {
return false;
}
};
+
+const testing = @import("../../../testing.zig");
+test "WebApi: HTML.event_listeners" {
+ try testing.htmlRunner("element/html/event_listeners.html", .{});
+}