Merge pull request #2739 from navidemad/fix-select-type-option-label

webapi: implement HTMLSelectElement.type and HTMLOptionElement.label
This commit is contained in:
Karl Seguin
2026-06-14 13:38:38 +08:00
committed by GitHub
4 changed files with 55 additions and 0 deletions

View File

@@ -29,6 +29,23 @@
testing.expectEqual('Text 3', $('#opt3').text)
</script>
<option id="opt_labelled" label="Explicit Label">Inner Text</option>
<script id="label">
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-option-label
// No label attribute: falls back to the text.
testing.expectEqual('Text 1', $('#opt1').label)
// label attribute present and non-empty: returned as-is.
testing.expectEqual('Explicit Label', $('#opt_labelled').label)
// Setting reflects to the label content attribute.
$('#opt1').label = 'Set Label'
testing.expectEqual('Set Label', $('#opt1').label)
testing.expectEqual('Set Label', $('#opt1').getAttribute('label'))
// An empty label attribute falls back to the text, per spec.
$('#opt1').setAttribute('label', '')
testing.expectEqual('Text 1', $('#opt1').label)
</script>
<script id="text_set">
$('#opt1').text = 'New Text 1'
testing.expectEqual('New Text 1', $('#opt1').text)

View File

@@ -142,6 +142,20 @@
}
</script>
<script id="type_reflects_multiple">
{
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-select-type
testing.expectEqual('select-one', $('#select1').type)
testing.expectEqual('select-multiple', $('#select_multi').type)
// type tracks the multiple attribute, it is not stored independently
const sel = document.createElement('select')
testing.expectEqual('select-one', sel.type)
sel.multiple = true
testing.expectEqual('select-multiple', sel.type)
}
</script>
<script id="multiple_setValue">
{
const sel = $('#select_multi')

View File

@@ -108,6 +108,21 @@ pub fn setName(self: *Option, name: []const u8, frame: *Frame) !void {
try self.asElement().setAttributeSafe(comptime .wrap("name"), .wrap(name), frame);
}
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-option-label
// On getting, return the `label` content attribute if present and non-empty,
// otherwise the value of the `text` IDL attribute. On setting, reflect to the
// `label` content attribute.
pub fn getLabel(self: *const Option, frame: *Frame) []const u8 {
if (self.asConstElement().getAttributeSafe(comptime .wrap("label"))) |label| {
if (label.len != 0) return label;
}
return self.getText(frame);
}
pub fn setLabel(self: *Option, label: []const u8, frame: *Frame) !void {
try self.asElement().setAttributeSafe(comptime .wrap("label"), .wrap(label), frame);
}
pub const JsApi = struct {
pub const bridge = js.Bridge(Option);
@@ -119,6 +134,7 @@ pub const JsApi = struct {
pub const value = bridge.accessor(Option.getValue, Option.setValue, .{ .ce_reactions = true });
pub const text = bridge.accessor(Option.getText, Option.setText, .{ .ce_reactions = true });
pub const label = bridge.accessor(Option.getLabel, Option.setLabel, .{ .ce_reactions = true });
pub const selected = bridge.accessor(Option.getSelected, Option.setSelected, .{});
pub const defaultSelected = bridge.accessor(Option.getDefaultSelected, null, .{});
pub const disabled = bridge.accessor(Option.getDisabled, Option.setDisabled, .{ .ce_reactions = true });

View File

@@ -129,6 +129,13 @@ pub fn getMultiple(self: *const Select) bool {
return self.asConstElement().getAttributeSafe(comptime .wrap("multiple")) != null;
}
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-select-type
// The `type` IDL attribute reflects the element's mode: "select-multiple" when
// the `multiple` attribute is present, "select-one" otherwise.
pub fn getType(self: *const Select) []const u8 {
return if (self.getMultiple()) "select-multiple" else "select-one";
}
pub fn setMultiple(self: *Select, multiple: bool, frame: *Frame) !void {
if (multiple) {
try self.asElement().setAttributeSafe(comptime .wrap("multiple"), .wrap(""), frame);
@@ -318,6 +325,7 @@ pub const JsApi = struct {
};
pub const value = bridge.accessor(Select.getValue, Select.setValue, .{});
pub const @"type" = bridge.accessor(Select.getType, null, .{});
pub const selectedIndex = bridge.accessor(Select.getSelectedIndex, Select.setSelectedIndex, .{});
pub const multiple = bridge.accessor(Select.getMultiple, Select.setMultiple, .{ .ce_reactions = true });
pub const disabled = bridge.accessor(Select.getDisabled, Select.setDisabled, .{ .ce_reactions = true });