mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-20 19:45:12 +00:00
LibWeb/HTML: Add the command attribute to the button element
This commit adds the getter and setter for the command attribute to the button element. Executing commands is not implemented yet.
This commit is contained in:
parent
629cd3c42a
commit
b2db07f002
Notes:
github-actions[bot]
2025-04-18 11:11:19 +00:00
Author: https://github.com/skyz1 Commit: https://github.com/LadybirdBrowser/ladybird/commit/b2db07f002d Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4220 Reviewed-by: https://github.com/tcl3 ✅
6 changed files with 140 additions and 0 deletions
|
@ -173,4 +173,50 @@ bool HTMLButtonElement::is_focusable() const
|
|||
return enabled();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-button-command
|
||||
String HTMLButtonElement::command() const
|
||||
{
|
||||
// 1. Let command be this's command attribute.
|
||||
auto command = get_attribute(AttributeNames::command);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/form-elements.html#attr-button-command
|
||||
// The command attribute is an enumerated attribute with the following keywords and states:
|
||||
// Keyword State Brief description
|
||||
// toggle-popover Toggle Popover Shows or hides the targeted popover element.
|
||||
// show-popover Show Popover Shows the targeted popover element.
|
||||
// hide-popover Hide Popover Hides the targeted popover element.
|
||||
// close Close Closes the targeted dialog element.
|
||||
// show-modal Show Modal Opens the targeted dialog element as modal.
|
||||
// A custom command keyword Custom Only dispatches the command event on the targeted element.
|
||||
Array valid_values { "toggle-popover"_string, "show-popover"_string, "hide-popover"_string, "close"_string, "show-modal"_string };
|
||||
|
||||
// 2. If command is in the Custom state, then return command's value.
|
||||
// A custom command keyword is a string that starts with "--".
|
||||
if (command.has_value() && command.value().starts_with_bytes("--"sv)) {
|
||||
return command.value();
|
||||
}
|
||||
|
||||
// NOTE: Steps are re-ordered a bit.
|
||||
|
||||
// 4. Return the keword corresponding to the value of command.return
|
||||
if (command.has_value()) {
|
||||
auto command_value = command.value();
|
||||
for (auto const& value : valid_values) {
|
||||
if (value.equals_ignoring_ascii_case(command_value)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. If command is in the Unknown state, then return the empty string.
|
||||
// The attribute's missing value default and invalid value default are both the Unknown state.
|
||||
return {};
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:dom-button-command-2
|
||||
WebIDL::ExceptionOr<void> HTMLButtonElement::set_command(String const& value)
|
||||
{
|
||||
return set_attribute(AttributeNames::command, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -80,6 +80,9 @@ public:
|
|||
virtual bool has_activation_behavior() const override;
|
||||
virtual void activation_behavior(DOM::Event const&) override;
|
||||
|
||||
String command() const;
|
||||
WebIDL::ExceptionOr<void> set_command(String const& command);
|
||||
|
||||
private:
|
||||
virtual void visit_edges(Visitor&) override;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ enum ButtonTypeState {
|
|||
interface HTMLButtonElement : HTMLElement {
|
||||
[HTMLConstructor] constructor();
|
||||
|
||||
[CEReactions] attribute DOMString command;
|
||||
[CEReactions, Reflect] attribute boolean disabled;
|
||||
readonly attribute HTMLFormElement? form;
|
||||
[CEReactions] attribute USVString formAction;
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 16 tests
|
||||
|
||||
16 Pass
|
||||
Pass invoker should reflect properly
|
||||
Pass invoker should reflect show-modal properly
|
||||
Pass invoker should reflect toggle-popover properly
|
||||
Pass invoker should reflect hide-popover properly
|
||||
Pass invoker should reflect show-popover properly
|
||||
Pass invoker should reflect close properly
|
||||
Pass invoker should reflect --custom properly
|
||||
Pass invoker should reflect odd cased sHoW-MoDaL properly - as show-modal
|
||||
Pass invoker should reflect odd cased tOgGlE-pOpOvEr properly - as toggle-popover
|
||||
Pass invoker should reflect odd cased hIdE-pOpOvEr properly - as hide-popover
|
||||
Pass invoker should reflect odd cased sHoW-pOpOvEr properly - as show-popover
|
||||
Pass invoker should reflect odd cased ClOsE properly - as close
|
||||
Pass invoker should reflect odd cased --cUsToM properly - as --cUsToM
|
||||
Pass invoker should reflect the invalid value "invalid" as the empty string
|
||||
Pass invoker should reflect the invalid value "show-invalid" as the empty string
|
||||
Pass invoker should reflect the invalid value "foo-bar" as the empty string
|
|
@ -0,0 +1,42 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" />
|
||||
<meta name="timeout" content="long" />
|
||||
<link rel="help" href="https://open-ui.org/components/invokers.explainer/" />
|
||||
<script src="../../../../resources/testharness.js"></script>
|
||||
<script src="../../../../resources/testharnessreport.js"></script>
|
||||
<script src="../../../../resources/testdriver.js"></script>
|
||||
<script src="../../../../resources/testdriver-actions.js"></script>
|
||||
<script src="../../../../resources/testdriver-vendor.js"></script>
|
||||
<script src="resources/invoker-utils.js"></script>
|
||||
|
||||
<div id="invokee"></div>
|
||||
<button id="invokerbutton" commandfor="invokee"></button>
|
||||
|
||||
<script>
|
||||
['', 'show-modal', 'toggle-popover', 'hide-popover', 'show-popover', 'close', '--custom'].forEach(command => {
|
||||
test(function (t) {
|
||||
invokerbutton.command = command
|
||||
assert_equals(invokerbutton.command, command, `invoker should reflect ${command} properly`);
|
||||
}, `invoker should reflect ${command} properly`);
|
||||
});
|
||||
[
|
||||
['sHoW-MoDaL', 'show-modal'],
|
||||
['tOgGlE-pOpOvEr', 'toggle-popover'],
|
||||
['hIdE-pOpOvEr', 'hide-popover'],
|
||||
['sHoW-pOpOvEr', 'show-popover'],
|
||||
['ClOsE', 'close'],
|
||||
['--cUsToM', '--cUsToM'
|
||||
]].forEach(([cased, command]) => {
|
||||
test(function (t) {
|
||||
invokerbutton.command = cased
|
||||
assert_equals(invokerbutton.command, command, `invoker should reflect odd cased ${cased} properly - as ${command}`);
|
||||
}, `invoker should reflect odd cased ${cased} properly - as ${command}`);
|
||||
});
|
||||
['invalid', 'show-invalid', 'foo-bar'].forEach(command => {
|
||||
test(function (t) {
|
||||
invokerbutton.command = command
|
||||
assert_equals(invokerbutton.command, '', `invoker should reflect the invalid value "${command}" as the empty string`);
|
||||
}, `invoker should reflect the invalid value "${command}" as the empty string`);
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,27 @@
|
|||
function waitForRender() {
|
||||
return new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));
|
||||
}
|
||||
async function clickOn(element) {
|
||||
await waitForRender();
|
||||
let rect = element.getBoundingClientRect();
|
||||
let actions = new test_driver.Actions();
|
||||
// FIXME: Switch to pointerMove(0, 0, {origin: element}) once
|
||||
// https://github.com/web-platform-tests/wpt/issues/41257 is fixed.
|
||||
await actions
|
||||
.pointerMove(Math.round(rect.x + rect.width / 2), Math.round(rect.y + rect.height / 2), {})
|
||||
.pointerDown({button: actions.ButtonType.LEFT})
|
||||
.pointerUp({button: actions.ButtonType.LEFT})
|
||||
.send();
|
||||
await waitForRender();
|
||||
}
|
||||
async function hoverOver(element) {
|
||||
await waitForRender();
|
||||
let rect = element.getBoundingClientRect();
|
||||
let actions = new test_driver.Actions();
|
||||
// FIXME: Switch to pointerMove(0, 0, {origin: element}) once
|
||||
// https://github.com/web-platform-tests/wpt/issues/41257 is fixed.
|
||||
await actions
|
||||
.pointerMove(Math.round(rect.x + rect.width / 2), Math.round(rect.y + rect.height / 2), {})
|
||||
.send();
|
||||
await waitForRender();
|
||||
}
|
Loading…
Add table
Reference in a new issue