diff --git a/src/browser/webapi/Element.zig b/src/browser/webapi/Element.zig index 98bbbf7b..c89fe421 100644 --- a/src/browser/webapi/Element.zig +++ b/src/browser/webapi/Element.zig @@ -990,6 +990,11 @@ pub fn cloneElement(self: *Element, deep: bool, page: *Page) !*Node { const node = try page.createElement(namespace_uri, tag_name, self._attributes); + // Allow element-specific types to copy their runtime state + _ = Element.Build.call(node.as(Element), "cloned", .{ self, node.as(Element), page }) catch |err| { + log.err(.dom, "element.clone.failed", .{ .err = err }); + }; + if (deep) { var child_it = self.asNode().childrenIterator(); while (child_it.next()) |child| { diff --git a/src/browser/webapi/element/html/Input.zig b/src/browser/webapi/element/html/Input.zig index 437cae8a..7bcd27a3 100644 --- a/src/browser/webapi/element/html/Input.zig +++ b/src/browser/webapi/element/html/Input.zig @@ -46,14 +46,16 @@ pub const Type = enum { range, date, time, - datetime_local, + @"datetime-local", month, week, color, pub fn fromString(str: []const u8) Type { // Longest type name is "datetime-local" at 14 chars - if (str.len > 32) return .text; + if (str.len > 32) { + return .text; + } var buf: [32]u8 = undefined; const lower = std.ascii.lowerString(&buf, str); @@ -61,10 +63,7 @@ pub const Type = enum { } pub fn toString(self: Type) []const u8 { - return switch (self) { - .datetime_local => "datetime-local", - else => @tagName(self), - }; + return @tagName(self); } }; @@ -76,6 +75,7 @@ _checked: bool = false, _checked_dirty: bool = false, _input_type: Type = .text, _selected: bool = false, +_indeterminate: bool = false, pub fn asElement(self: *Input) *Element { return self._proto._proto; @@ -129,6 +129,14 @@ pub fn setChecked(self: *Input, checked: bool, page: *Page) !void { self._checked_dirty = true; } +pub fn getIndeterminate(self: *const Input) bool { + return self._indeterminate; +} + +pub fn setIndeterminate(self: *Input, value: bool) !void { + self._indeterminate = value; +} + pub fn getDefaultChecked(self: *const Input) bool { return self._default_checked; } @@ -342,6 +350,7 @@ pub const JsApi = struct { pub const size = bridge.accessor(Input.getSize, Input.setSize, .{}); pub const src = bridge.accessor(Input.getSrc, Input.setSrc, .{}); pub const form = bridge.accessor(Input.getForm, null, .{}); + pub const indeterminate = bridge.accessor(Input.getIndeterminate, Input.setIndeterminate, .{}); pub const select = bridge.function(Input.select, .{}); }; @@ -404,6 +413,18 @@ pub const Build = struct { }, } } + + pub fn cloned(source_element: *Element, cloned_element: *Element, _: *Page) !void { + const source = source_element.as(Input); + const clone = cloned_element.as(Input); + + // Copy runtime state from source to clone + clone._value = source._value; + clone._checked = source._checked; + clone._checked_dirty = source._checked_dirty; + clone._selected = source._selected; + clone._indeterminate = source._indeterminate; + } }; const testing = @import("../../../../testing.zig");