diff --git a/src/browser/tests/element/html/htmlelement-props.html b/src/browser/tests/element/html/htmlelement-props.html index 6e625d4f6..3eefcd01e 100644 --- a/src/browser/tests/element/html/htmlelement-props.html +++ b/src/browser/tests/element/html/htmlelement-props.html @@ -82,3 +82,44 @@ testing.expectEqual(-1, d3.tabIndex); } + + diff --git a/src/browser/webapi/element/Html.zig b/src/browser/webapi/element/Html.zig index 0b4333085..9dbe089c6 100644 --- a/src/browser/webapi/element/Html.zig +++ b/src/browser/webapi/element/Html.zig @@ -471,6 +471,30 @@ pub fn setTranslate(self: *HtmlElement, translate: bool, frame: *Frame) !void { try self.asElement().setAttributeSafe(comptime .wrap("translate"), .wrap(if (translate) "yes" else "no"), frame); } +// The draggable IDL attribute reflects the enumerated content attribute: +// "true" => true, "false" => false, anything else (or no attribute) is the +// auto state, which defaults to true only for and with an href. +// https://html.spec.whatwg.org/multipage/dnd.html#the-draggable-attribute +pub fn getDraggable(self: *HtmlElement) bool { + if (self.asElement().getAttributeSafe(comptime .wrap("draggable"))) |value| { + if (std.ascii.eqlIgnoreCase(value, "true")) { + return true; + } + if (std.ascii.eqlIgnoreCase(value, "false")) { + return false; + } + } + return switch (self._type) { + .img => true, + .anchor => self.asElement().getAttributeSafe(comptime .wrap("href")) != null, + else => false, + }; +} + +pub fn setDraggable(self: *HtmlElement, draggable: bool, frame: *Frame) !void { + try self.asElement().setAttributeSafe(comptime .wrap("draggable"), .wrap(if (draggable) "true" else "false"), frame); +} + // accessKeyLabel: the UA-assigned shortcut for a valid (single character) // accesskey, or the empty string. We report an Alt+ chord like Chromium. pub fn getAccessKeyLabel(self: *HtmlElement, frame: *Frame) ![]const u8 { @@ -1808,6 +1832,7 @@ pub const JsApi = struct { pub const accessKey = bridge.accessor(HtmlElement.getAccessKey, HtmlElement.setAccessKey, .{ .ce_reactions = true }); pub const autofocus = bridge.accessor(HtmlElement.getAutofocus, HtmlElement.setAutofocus, .{ .ce_reactions = true }); pub const dir = reflect.enumerated("dir", &.{ "ltr", "rtl", "auto" }, .{}); + pub const draggable = bridge.accessor(HtmlElement.getDraggable, HtmlElement.setDraggable, .{ .ce_reactions = true }); pub const hidden = bridge.accessor(HtmlElement.getHidden, HtmlElement.setHidden, .{ .ce_reactions = true }); pub const translate = bridge.accessor(HtmlElement.getTranslate, HtmlElement.setTranslate, .{ .ce_reactions = true }); pub const accessKeyLabel = bridge.accessor(HtmlElement.getAccessKeyLabel, null, .{});