mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-07 21:59:54 +00:00
LibWeb: Allow all elements with tabindex attribute to be focusable
This commit is contained in:
parent
154e9db033
commit
3bc061d028
Notes:
github-actions[bot]
2025-11-12 12:58:21 +00:00
Author: https://github.com/lpas
Commit: 3bc061d028
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6780
Reviewed-by: https://github.com/gmta ✅
5 changed files with 183 additions and 1 deletions
|
|
@ -4277,6 +4277,12 @@ bool Element::should_indicate_focus() const
|
|||
return false;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/interaction.html#tabindex-value
|
||||
bool Element::is_focusable() const
|
||||
{
|
||||
return HTML::parse_integer(get_attribute_value(HTML::AttributeNames::tabindex)).has_value();
|
||||
}
|
||||
|
||||
void Element::set_had_duplicate_attribute_during_tokenization(Badge<HTML::HTMLParser>)
|
||||
{
|
||||
m_had_duplicate_attribute_during_tokenization = true;
|
||||
|
|
|
|||
|
|
@ -301,6 +301,7 @@ public:
|
|||
virtual void did_receive_focus() { }
|
||||
virtual void did_lose_focus() { }
|
||||
bool should_indicate_focus() const;
|
||||
virtual bool is_focusable() const override;
|
||||
|
||||
static GC::Ptr<Layout::NodeWithStyle> create_layout_node_for_display_type(DOM::Document&, CSS::Display const&, GC::Ref<CSS::ComputedProperties>, Element*);
|
||||
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ void HTMLElement::set_dir(String const& dir)
|
|||
|
||||
bool HTMLElement::is_focusable() const
|
||||
{
|
||||
return is_editing_host() || get_attribute(HTML::AttributeNames::tabindex).has_value();
|
||||
return Base::is_focusable() || is_editing_host();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/interaction.html#dom-iscontenteditable
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 35 tests
|
||||
|
||||
31 Pass
|
||||
4 Fail
|
||||
Pass a should not be focusable by default.
|
||||
Pass a[href] should be focusable by default.
|
||||
Pass button should be focusable by default.
|
||||
Pass input[type="hidden"] should not be focusable by default.
|
||||
Pass input[type="button"] should be focusable by default.
|
||||
Pass select should be focusable by default.
|
||||
Pass textarea should be focusable by default.
|
||||
Pass #summary-out should not be focusable by default.
|
||||
Fail #summary-first should be focusable by default.
|
||||
Pass #summary-second should not be focusable by default.
|
||||
Pass [contenteditable] should be focusable by default.
|
||||
Pass iframe should be focusable by default.
|
||||
Pass #svg-a should not be focusable by default.
|
||||
Pass #svg-text should not be focusable by default.
|
||||
Pass img should not be focusable by default.
|
||||
Fail A with tabindex=0 should be focusable.
|
||||
Pass a with tabindex=0 should be focusable.
|
||||
Pass text with tabindex=0 should be focusable.
|
||||
Pass SUMMARY#summary-out-tabindex0 with tabindex=0 should be focusable.
|
||||
Pass SUMMARY#summary-second-tabindex0 with tabindex=0 should be focusable.
|
||||
Pass IMG with tabindex=0 should be focusable.
|
||||
Fail A with tabindex=-1 should be focusable.
|
||||
Pass a with tabindex=-1 should be focusable.
|
||||
Pass text with tabindex=-1 should be focusable.
|
||||
Pass SUMMARY#summary-out-tabindex-negative with tabindex=-1 should be focusable.
|
||||
Pass SUMMARY#summary-second-tabindex-negative with tabindex=-1 should be focusable.
|
||||
Pass IMG with tabindex=-1 should be focusable.
|
||||
Pass A with tabindex=invalid should not be focusable.
|
||||
Pass A#with-href with tabindex=invalid should be focusable.
|
||||
Pass a with tabindex=invalid should not be focusable.
|
||||
Fail a#with-href with tabindex=invalid should be focusable.
|
||||
Pass text with tabindex=invalid should not be focusable.
|
||||
Pass DIV with tabindex=invalid should not be focusable.
|
||||
Pass SUMMARY#summary-out-tabindex-invalid with tabindex=invalid should not be focusable.
|
||||
Pass IMG with tabindex=invalid should not be focusable.
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#specially-focusable">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<body>
|
||||
<div id="default-samples">
|
||||
<a></a>
|
||||
<a href=""></a>
|
||||
<button></button>
|
||||
<input type="hidden">
|
||||
<input type="button">
|
||||
<select><option>abc</option></select>
|
||||
<textarea></textarea>
|
||||
<summary id="summary-out"></summary>
|
||||
<details open><summary id="summary-first"></summary><summary id="summary-second"></summary></details>
|
||||
<div contenteditable="true"></div>
|
||||
<iframe></iframe>
|
||||
<svg><a id="svg-a"></a></svg>
|
||||
<svg><text id="svg-text"></text></svg>
|
||||
<img>
|
||||
</div>
|
||||
<script>
|
||||
setup({ explicit_done: true });
|
||||
window.addEventListener("load", runTests);
|
||||
|
||||
function runTests() {
|
||||
const defaultList = [
|
||||
['a', false],
|
||||
['a[href]', true],
|
||||
['button', true],
|
||||
['input[type="hidden"]', false],
|
||||
['input[type="button"]', true],
|
||||
['select', true],
|
||||
['textarea', true],
|
||||
['#summary-out', false],
|
||||
['#summary-first', true],
|
||||
['#summary-second', false],
|
||||
['[contenteditable]', true],
|
||||
['iframe', true],
|
||||
['#svg-a', false],
|
||||
['#svg-text', false],
|
||||
['img', false],
|
||||
];
|
||||
for (entry of defaultList) {
|
||||
test(() => {
|
||||
var element = document.querySelector('#default-samples ' + entry[0]);
|
||||
element.focus();
|
||||
if (entry[1])
|
||||
assert_equals(document.activeElement, element);
|
||||
else
|
||||
assert_not_equals(document.activeElement, element);
|
||||
}, entry[0] + ' should ' + (entry[1] ? '' : 'not ') + 'be focusable by default.');
|
||||
}
|
||||
|
||||
runTests_tabindex0();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div id="tabindex-0">
|
||||
<a tabindex="0"></a>
|
||||
<svg><a tabindex="0"></a></svg>
|
||||
<svg><text tabindex="0"></text></svg>
|
||||
<summary tabindex="0" id="summary-out-tabindex0"></summary>
|
||||
<details open><summary id="summary-first"></summary><summary tabindex="0" id="summary-second-tabindex0"></summary></details>
|
||||
<img tabindex="0">
|
||||
</div>
|
||||
<script>
|
||||
function runTests_tabindex0() {
|
||||
for (element of document.querySelectorAll('#tabindex-0 [tabindex]')) {
|
||||
var elementDesc = element.tagName;
|
||||
if (element.id)
|
||||
elementDesc += '#' + element.id;
|
||||
test(() => {
|
||||
element.focus();
|
||||
assert_equals(document.activeElement, element);
|
||||
}, elementDesc + ' with tabindex=0 should be focusable.');
|
||||
}
|
||||
|
||||
runTests_tabindex_negative();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div id="tabindex-negative">
|
||||
<a tabindex="-1"></a>
|
||||
<svg><a tabindex="-1"></a></svg>
|
||||
<svg><text tabindex="-1"></text></svg>
|
||||
<summary tabindex="-1" id="summary-out-tabindex-negative"></summary>
|
||||
<details open><summary id="summary-first"></summary><summary tabindex="0" id="summary-second-tabindex-negative"></summary></details>
|
||||
<img tabindex="-1">
|
||||
</div>
|
||||
<script>
|
||||
function runTests_tabindex_negative() {
|
||||
for (element of document.querySelectorAll('#tabindex-negative [tabindex]')) {
|
||||
var elementDesc = element.tagName;
|
||||
if (element.id)
|
||||
elementDesc += '#' + element.id;
|
||||
test(() => {
|
||||
element.focus();
|
||||
assert_equals(document.activeElement, element);
|
||||
}, elementDesc + ' with tabindex=-1 should be focusable.');
|
||||
}
|
||||
|
||||
runTests_tabindex_invalid();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div id="tabindex-invalid">
|
||||
<a tabindex="invalid"></a>
|
||||
<a href="#" tabindex="invalid" id="with-href" data-focusable=true></a>
|
||||
<svg><a tabindex="invalid"></a></svg>
|
||||
<svg><a href="#" tabindex="invalid" id="with-href" data-focusable=true></a></svg>
|
||||
<svg><text tabindex="invalid"></text></svg>
|
||||
<div tabindex="invalid"></div>
|
||||
<summary tabindex="invalid" id="summary-out-tabindex-invalid"></summary>
|
||||
<img tabindex="invalid">
|
||||
</div>
|
||||
<script>
|
||||
function runTests_tabindex_invalid() {
|
||||
for (element of document.querySelectorAll('#tabindex-invalid [tabindex]')) {
|
||||
var focusable = element.dataset && element.dataset.focusable;
|
||||
var elementDesc = element.tagName;
|
||||
if (element.id)
|
||||
elementDesc += '#' + element.id;
|
||||
test(() => {
|
||||
element.focus();
|
||||
focusable ? assert_equals(document.activeElement, element)
|
||||
: assert_not_equals(document.activeElement, element);
|
||||
}, `${elementDesc} with tabindex=invalid should ${focusable ? "be" : "not be"} focusable.`);
|
||||
}
|
||||
|
||||
done();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
Loading…
Add table
Add a link
Reference in a new issue