mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-08-01 02:06:17 -04:00
webapi: implement HTMLSelectElement.type and HTMLOptionElement.label
Both IDL attributes were unimplemented and evaluated to `undefined`. `select.type` reflects the element's mode: "select-multiple" when the `multiple` attribute is present, "select-one" otherwise (derived from the existing `getMultiple()`). `option.label` returns the `label` content attribute when present and non-empty, otherwise the value of the `text` IDL attribute. Both match the HTML Living Standard. Select-enhancement libraries branch on `select.type` to choose single- vs multi-select code paths; reading `undefined` there made them take a dead path and throw during initialization. Closes #2738
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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 });
|
||||
|
||||
Reference in New Issue
Block a user