diff --git a/src/browser/webapi/Document.zig b/src/browser/webapi/Document.zig index e78b1ea60..281328f25 100644 --- a/src/browser/webapi/Document.zig +++ b/src/browser/webapi/Document.zig @@ -21,6 +21,7 @@ const lp = @import("lightpanda"); const js = @import("../js/js.zig"); const Frame = @import("../Frame.zig"); +const Window = @import("Window.zig"); const URL = @import("../URL.zig"); const idna = @import("../../sys/idna.zig"); const public_suffix_list = @import("../../data/public_suffix_list.zig"); @@ -89,6 +90,21 @@ pub fn setOnSelectionChange(self: *Document, listener: ?js.Function) !void { } } +// Stored in the frame's attribute-listener map (like element and ShadowRoot +// property handlers), which the dispatch propagation path consults for any +// event target. +pub fn getOnClick(self: *Document, frame: *Frame) ?js.Function.Global { + return frame._event_target_attr_listeners.get(.{ .target = self.asEventTarget(), .handler = .onclick }); +} + +pub fn setOnClick(self: *Document, setter: ?Window.FunctionSetter, frame: *Frame) !void { + if (Window.getFunctionFromSetter(setter)) |cb| { + try frame._event_target_attr_listeners.put(frame.arena, .{ .target = self.asEventTarget(), .handler = .onclick }, cb); + } else { + _ = frame._event_target_attr_listeners.remove(.{ .target = self.asEventTarget(), .handler = .onclick }); + } +} + pub const Type = union(enum) { generic, html: *HTMLDocument, @@ -1265,6 +1281,7 @@ pub const JsApi = struct { } pub const onselectionchange = bridge.accessor(Document.getOnSelectionChange, Document.setOnSelectionChange, .{}); + pub const onclick = bridge.accessor(Document.getOnClick, Document.setOnClick, .{}); pub const URL = bridge.accessor(Document.getURL, null, .{}); pub const location = bridge.accessor(Document.getLocation, Document.setLocation, .{}); pub const documentURI = bridge.accessor(Document.getURL, null, .{}); diff --git a/src/browser/webapi/Window.zig b/src/browser/webapi/Window.zig index e374d0168..b83f10ee5 100644 --- a/src/browser/webapi/Window.zig +++ b/src/browser/webapi/Window.zig @@ -425,6 +425,21 @@ pub fn setOnScroll(self: *Window, setter: ?FunctionSetter) void { self._on_scroll = getFunctionFromSetter(setter); } +// Stored in the frame's attribute-listener map (like element and ShadowRoot +// property handlers), which the dispatch propagation path consults for any +// event target. +pub fn getOnClick(self: *Window, frame: *Frame) ?js.Function.Global { + return frame._event_target_attr_listeners.get(.{ .target = self.asEventTarget(), .handler = .onclick }); +} + +pub fn setOnClick(self: *Window, setter: ?FunctionSetter, frame: *Frame) !void { + if (getFunctionFromSetter(setter)) |cb| { + try frame._event_target_attr_listeners.put(frame.arena, .{ .target = self.asEventTarget(), .handler = .onclick }, cb); + } else { + _ = frame._event_target_attr_listeners.remove(.{ .target = self.asEventTarget(), .handler = .onclick }); + } +} + // The "window-reflecting body element event handler set" (HTML spec): these // event handlers of body and frameset elements are aliases for the Window's. // Returns the Window storage slot for the given content attribute name, or @@ -1159,6 +1174,7 @@ pub const JsApi = struct { pub const onfocus = bridge.accessor(Window.getOnFocus, Window.setOnFocus, .{}); pub const onresize = bridge.accessor(Window.getOnResize, Window.setOnResize, .{}); pub const onscroll = bridge.accessor(Window.getOnScroll, Window.setOnScroll, .{}); + pub const onclick = bridge.accessor(Window.getOnClick, Window.setOnClick, .{}); pub const onmessage = bridge.accessor(Window.getOnMessage, Window.setOnMessage, .{}); pub const onrejectionhandled = bridge.accessor(Window.getOnRejectionHandled, Window.setOnRejectionHandled, .{}); pub const onunhandledrejection = bridge.accessor(Window.getOnUnhandledRejection, Window.setOnUnhandledRejection, .{});