diff --git a/src/browser/interactive.zig b/src/browser/interactive.zig
index cf623f6c..b0428a6c 100644
--- a/src/browser/interactive.zig
+++ b/src/browser/interactive.zig
@@ -19,6 +19,7 @@
const std = @import("std");
const Page = @import("Page.zig");
+const URL = @import("URL.zig");
const TreeWalker = @import("webapi/TreeWalker.zig");
const Element = @import("webapi/Element.zig");
const Node = @import("webapi/Node.zig");
@@ -125,8 +126,8 @@ pub const InteractiveElement = struct {
/// Collect all interactive elements under `root`.
pub fn collectInteractiveElements(
root: *Node,
- page: *Page,
arena: Allocator,
+ page: *Page,
) ![]InteractiveElement {
// Pre-build a map of event_target pointer → event type names,
// so classify and getListenerTypes are both O(1) per element.
@@ -134,7 +135,7 @@ pub fn collectInteractiveElements(
var results: std.ArrayList(InteractiveElement) = .empty;
- var tw = TreeWalker.FullExcludeSelf.init(root, .{});
+ var tw = TreeWalker.Full.init(root, .{});
while (tw.next()) |node| {
const el = node.is(Element) orelse continue;
const html_el = el.is(Element.Html) orelse continue;
@@ -163,7 +164,10 @@ pub fn collectInteractiveElements(
.tab_index = html_el.getTabIndex(),
.id = el.getAttributeSafe(comptime .wrap("id")),
.class = el.getAttributeSafe(comptime .wrap("class")),
- .href = el.getAttributeSafe(comptime .wrap("href")),
+ .href = if (el.getAttributeSafe(comptime .wrap("href"))) |href|
+ URL.resolve(arena, page.base(), href, .{ .encode = true }) catch href
+ else
+ null,
.input_type = getInputType(el),
.value = getInputValue(el),
.element_name = el.getAttributeSafe(comptime .wrap("name")),
@@ -348,7 +352,34 @@ fn getTextContent(node: *Node) ?[]const u8 {
}
fn isDisabled(el: *Element) bool {
- return el.getAttributeSafe(comptime .wrap("disabled")) != null;
+ if (el.getAttributeSafe(comptime .wrap("disabled")) != null) return true;
+ return isDisabledByFieldset(el);
+}
+
+/// Check if an element is disabled by an ancestor