diff --git a/src/browser/tests/element/html/image.html b/src/browser/tests/element/html/image.html
index b9cb8153..b834aebf 100644
--- a/src/browser/tests/element/html/image.html
+++ b/src/browser/tests/element/html/image.html
@@ -97,3 +97,62 @@
testing.expectEqual('lazy', img.getAttribute('loading'));
}
+
+
+
+
+
+
diff --git a/src/browser/webapi/element/html/Image.zig b/src/browser/webapi/element/html/Image.zig
index 41482ec9..4a675e6b 100644
--- a/src/browser/webapi/element/html/Image.zig
+++ b/src/browser/webapi/element/html/Image.zig
@@ -5,6 +5,8 @@ const URL = @import("../../../URL.zig");
const Node = @import("../../Node.zig");
const Element = @import("../../Element.zig");
const HtmlElement = @import("../Html.zig");
+const Event = @import("../../Event.zig");
+const log = @import("../../../../log.zig");
const Image = @This();
_proto: *HtmlElement,
@@ -47,6 +49,41 @@ pub fn getSrc(self: *const Image, page: *Page) ![]const u8 {
pub fn setSrc(self: *Image, value: []const u8, page: *Page) !void {
try self.asElement().setAttributeSafe(comptime .wrap("src"), .wrap(value), page);
+
+ const event_target = self.asNode().asEventTarget();
+
+ // Have to do this since `Scheduler` only allow passing a single arg.
+ const SetSrcCallback = struct {
+ page: *Page,
+ event_target: *@import("../../EventTarget.zig"),
+ };
+ const args = try page._factory.create(SetSrcCallback{
+ .page = page,
+ .event_target = event_target,
+ });
+ errdefer page._factory.destroy(args);
+
+ // We don't actually fetch the media, here we fake the load call.
+ try page.scheduler.add(
+ args,
+ struct {
+ fn wrap(raw: *anyopaque) anyerror!?u32 {
+ const _args: *SetSrcCallback = @ptrCast(@alignCast(raw));
+ const _page = _args.page;
+ defer _page._factory.destroy(_args);
+ // Dispatch.
+ const event = try Event.initTrusted("load", .{}, _page);
+ try _page._event_manager.dispatch(_args.event_target, event);
+
+ return null;
+ }
+ }.wrap,
+ 25,
+ .{
+ .low_priority = false,
+ .name = "Image.setSrc",
+ },
+ );
}
pub fn getAlt(self: *const Image) []const u8 {
@@ -115,6 +152,40 @@ pub const JsApi = struct {
pub const loading = bridge.accessor(Image.getLoading, Image.setLoading, .{});
};
+/// Argument passed to `dispatchLoadEvent`.
+const CallbackParams = struct { page: *Page, element: *Element };
+
+/// Callback passed to `Scheduler` to execute load listeners.
+fn dispatchLoadEvent(raw: *anyopaque) !?u32 {
+ const _args: *CallbackParams = @ptrCast(@alignCast(raw));
+ const _page = _args.page;
+ defer _page._factory.destroy(_args);
+
+ const _element = _args.element;
+ const _img = _element.as(Image);
+ const event_target = _element.asEventTarget();
+ const event = try Event.initTrusted("load", .{}, _page);
+
+ // If onload provided, dispatch with it.
+ if (_img.getOnLoad(_page)) |_on_load| {
+ var ls: js.Local.Scope = undefined;
+ _page.js.localScope(&ls);
+ defer ls.deinit();
+
+ try _page._event_manager.dispatchWithFunction(
+ event_target,
+ event,
+ _on_load.local(&ls.local),
+ .{ .context = "Image.onload" },
+ );
+ return null;
+ }
+
+ // Dispatch to addEventListener listeners.
+ try _page._event_manager.dispatch(event_target, event);
+ return null;
+}
+
const testing = @import("../../../../testing.zig");
test "WebApi: HTML.Image" {
try testing.htmlRunner("element/html/image.html", .{});