mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-10-02 09:25:01 -04:00
webapi: implement the HTMLElement.draggable IDL attribute
Reading el.draggable returned undefined for every element, and assigning it created a plain JS own property with no reflection onto the content attribute. Implement the reflected property per the HTML spec: the "true"/"false" keywords are matched ASCII case-insensitively, the auto state defaults to true for <img> and for <a> with an href (matching Chrome), and the setter writes the literal "true"/"false" onto the content attribute. Closes #3255
This commit is contained in:
2 files changed
+66
No files matched your search
@@ -82,3 +82,44 @@
|
||||
testing.expectEqual(-1, d3.tabIndex);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="draggable">
|
||||
{
|
||||
// Explicit keywords win, matched ASCII case-insensitively.
|
||||
const d = document.createElement('div');
|
||||
d.setAttribute('draggable', 'true');
|
||||
testing.expectEqual(true, d.draggable);
|
||||
d.setAttribute('draggable', 'TRUE');
|
||||
testing.expectEqual(true, d.draggable);
|
||||
d.setAttribute('draggable', 'false');
|
||||
testing.expectEqual(false, d.draggable);
|
||||
|
||||
// Missing or invalid values are the auto state: false for most elements.
|
||||
d.removeAttribute('draggable');
|
||||
testing.expectEqual(false, d.draggable);
|
||||
d.setAttribute('draggable', 'auto');
|
||||
testing.expectEqual(false, d.draggable);
|
||||
d.setAttribute('draggable', '');
|
||||
testing.expectEqual(false, d.draggable);
|
||||
|
||||
// Auto defaults to true for <img> and <a> with an href.
|
||||
const img = document.createElement('img');
|
||||
testing.expectEqual(true, img.draggable);
|
||||
img.setAttribute('draggable', 'false');
|
||||
testing.expectEqual(false, img.draggable);
|
||||
|
||||
const a = document.createElement('a');
|
||||
testing.expectEqual(false, a.draggable);
|
||||
a.setAttribute('href', '/x');
|
||||
testing.expectEqual(true, a.draggable);
|
||||
a.setAttribute('draggable', 'false');
|
||||
testing.expectEqual(false, a.draggable);
|
||||
|
||||
// The setter reflects to the content attribute as "true"/"false".
|
||||
const s = document.createElement('div');
|
||||
s.draggable = true;
|
||||
testing.expectEqual('true', s.getAttribute('draggable'));
|
||||
s.draggable = false;
|
||||
testing.expectEqual('false', s.getAttribute('draggable'));
|
||||
}
|
||||
</script>
|
||||
@@ -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 <img> and <a> 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, .{});
|
||||
|
||||
Reference in new issue
Block a user