mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-13 03:29:49 +00:00
LibWeb: Implement the labels
attribute for all labelable elements
This returns a `NodeList` of all the labels associated with the given element.
This commit is contained in:
parent
3dc86747f0
commit
2447a25753
Notes:
sideshowbarker
2024-07-16 20:39:14 +09:00
Author: https://github.com/tcl3
Commit: 2447a25753
Pull-request: https://github.com/SerenityOS/serenity/pull/24359
11 changed files with 89 additions and 7 deletions
21
Tests/LibWeb/Text/expected/HTML/HTMLElement-labels.txt
Normal file
21
Tests/LibWeb/Text/expected/HTML/HTMLElement-labels.txt
Normal file
|
@ -0,0 +1,21 @@
|
|||
input.labels.length: 1
|
||||
input.labels[0] === label: true
|
||||
input.labels always returns the same object: true
|
||||
meter.labels.length: 1
|
||||
meter.labels[0] === label: true
|
||||
meter.labels always returns the same object: true
|
||||
output.labels.length: 1
|
||||
output.labels[0] === label: true
|
||||
output.labels always returns the same object: true
|
||||
progress.labels.length: 1
|
||||
progress.labels[0] === label: true
|
||||
progress.labels always returns the same object: true
|
||||
select.labels.length: 1
|
||||
select.labels[0] === label: true
|
||||
select.labels always returns the same object: true
|
||||
textarea.labels.length: 1
|
||||
textarea.labels[0] === label: true
|
||||
textarea.labels always returns the same object: true
|
||||
input.labels returns null if input type is hidden: true
|
||||
input.labels.length after input type is changed from hidden: 1
|
||||
input.labels[0] === label after input type is changed from hidden: true
|
36
Tests/LibWeb/Text/input/HTML/HTMLElement-labels.html
Normal file
36
Tests/LibWeb/Text/input/HTML/HTMLElement-labels.html
Normal file
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="../include.js"></script>
|
||||
<script>
|
||||
test(() => {
|
||||
const labelableElements = ["input", "meter", "output", "progress", "select", "textarea"];
|
||||
for (const tagName of labelableElements) {
|
||||
const element = document.createElement(tagName);
|
||||
element.id = `${tagName}Id`;
|
||||
const label = document.createElement("label")
|
||||
label.htmlFor = `${tagName}Id`;
|
||||
document.body.appendChild(label);
|
||||
document.body.appendChild(element);
|
||||
const labels = element.labels;
|
||||
println(`${tagName}.labels.length: ${labels.length}`);
|
||||
println(`${tagName}.labels[0] === label: ${labels[0] === label}`);
|
||||
println(`${tagName}.labels always returns the same object: ${labels === element.labels}`);
|
||||
document.body.removeChild(label);
|
||||
document.body.removeChild(element);
|
||||
}
|
||||
|
||||
const inputElement = document.createElement("input");
|
||||
inputElement.type = "hidden";
|
||||
inputElement.id = "inputId"
|
||||
const label = document.createElement("label")
|
||||
label.htmlFor = 'inputId';
|
||||
document.body.appendChild(label);
|
||||
document.body.appendChild(inputElement);
|
||||
println(`input.labels returns null if input type is hidden: ${inputElement.labels === null}`);
|
||||
inputElement.type = "text";
|
||||
const labels = inputElement.labels;
|
||||
println(`input.labels.length after input type is changed from hidden: ${labels.length}`);
|
||||
println(`input.labels[0] === label after input type is changed from hidden: ${labels[0] === label}`);
|
||||
document.body.removeChild(label);
|
||||
document.body.removeChild(inputElement);
|
||||
});
|
||||
</script>
|
|
@ -31,6 +31,6 @@ interface HTMLButtonElement : HTMLElement {
|
|||
// FIXME: boolean reportValidity();
|
||||
// FIXME: undefined setCustomValidity(DOMString error);
|
||||
|
||||
// FIXME: readonly attribute NodeList labels;
|
||||
readonly attribute NodeList labels;
|
||||
};
|
||||
// FIXME: HTMLButtonElement includes PopoverInvokerElement;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <LibWeb/Bindings/HTMLElementPrototype.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOM/IDLEventListener.h>
|
||||
#include <LibWeb/DOM/LiveNodeList.h>
|
||||
#include <LibWeb/DOM/ShadowRoot.h>
|
||||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
#include <LibWeb/HTML/DOMStringMap.h>
|
||||
|
@ -20,6 +21,7 @@
|
|||
#include <LibWeb/HTML/HTMLBaseElement.h>
|
||||
#include <LibWeb/HTML/HTMLBodyElement.h>
|
||||
#include <LibWeb/HTML/HTMLElement.h>
|
||||
#include <LibWeb/HTML/HTMLLabelElement.h>
|
||||
#include <LibWeb/HTML/NavigableContainer.h>
|
||||
#include <LibWeb/HTML/VisibilityState.h>
|
||||
#include <LibWeb/HTML/Window.h>
|
||||
|
@ -436,6 +438,25 @@ bool HTMLElement::fire_a_synthetic_pointer_event(FlyString const& type, DOM::Ele
|
|||
return target.dispatch_event(event);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/forms.html#dom-lfe-labels-dev
|
||||
JS::GCPtr<DOM::NodeList> HTMLElement::labels()
|
||||
{
|
||||
// Labelable elements and all input elements have a live NodeList object associated with them that represents the list of label elements, in tree order,
|
||||
// whose labeled control is the element in question. The labels IDL attribute of labelable elements that are not form-associated custom elements,
|
||||
// and the labels IDL attribute of input elements, on getting, must return that NodeList object, and that same value must always be returned,
|
||||
// unless this element is an input element whose type attribute is in the Hidden state, in which case it must instead return null.
|
||||
if (!is_labelable())
|
||||
return {};
|
||||
|
||||
if (!m_labels) {
|
||||
m_labels = DOM::LiveNodeList::create(realm(), root(), DOM::LiveNodeList::Scope::Descendants, [&](auto& node) {
|
||||
return is<HTMLLabelElement>(node) && verify_cast<HTMLLabelElement>(node).control() == this;
|
||||
});
|
||||
}
|
||||
|
||||
return m_labels;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/interaction.html#dom-click
|
||||
void HTMLElement::click()
|
||||
{
|
||||
|
|
|
@ -68,6 +68,8 @@ public:
|
|||
// https://html.spec.whatwg.org/multipage/forms.html#category-label
|
||||
virtual bool is_labelable() const { return false; }
|
||||
|
||||
JS::GCPtr<DOM::NodeList> labels();
|
||||
|
||||
virtual Optional<ARIA::Role> default_role() const override;
|
||||
|
||||
String get_an_elements_target() const;
|
||||
|
@ -93,6 +95,8 @@ private:
|
|||
|
||||
JS::GCPtr<DOMStringMap> m_dataset;
|
||||
|
||||
JS::GCPtr<DOM::NodeList> m_labels;
|
||||
|
||||
enum class ContentEditableState {
|
||||
True,
|
||||
False,
|
||||
|
|
|
@ -54,7 +54,7 @@ interface HTMLInputElement : HTMLElement {
|
|||
boolean reportValidity();
|
||||
undefined setCustomValidity(DOMString error);
|
||||
|
||||
// FIXME: readonly attribute NodeList? labels;
|
||||
readonly attribute NodeList? labels;
|
||||
|
||||
undefined select();
|
||||
// FIXME: attribute unsigned long? selectionStart;
|
||||
|
|
|
@ -11,5 +11,5 @@ interface HTMLMeterElement : HTMLElement {
|
|||
[CEReactions] attribute double low;
|
||||
[CEReactions] attribute double high;
|
||||
[CEReactions] attribute double optimum;
|
||||
// FIXME: readonly attribute NodeList labels;
|
||||
readonly attribute NodeList labels;
|
||||
};
|
||||
|
|
|
@ -21,5 +21,5 @@ interface HTMLOutputElement : HTMLElement {
|
|||
// FIXME: boolean reportValidity();
|
||||
// FIXME: undefined setCustomValidity(DOMString error);
|
||||
|
||||
// FIXME: readonly attribute NodeList labels;
|
||||
readonly attribute NodeList labels;
|
||||
};
|
||||
|
|
|
@ -8,5 +8,5 @@ interface HTMLProgressElement : HTMLElement {
|
|||
[CEReactions] attribute double value;
|
||||
[CEReactions] attribute double max;
|
||||
readonly attribute double position;
|
||||
// FIXME: readonly attribute NodeList labels;
|
||||
readonly attribute NodeList labels;
|
||||
};
|
||||
|
|
|
@ -37,5 +37,5 @@ interface HTMLSelectElement : HTMLElement {
|
|||
// FIXME: boolean reportValidity();
|
||||
// FIXME: undefined setCustomValidity(DOMString error);
|
||||
|
||||
// FIXME: readonly attribute NodeList labels;
|
||||
readonly attribute NodeList labels;
|
||||
};
|
||||
|
|
|
@ -32,7 +32,7 @@ interface HTMLTextAreaElement : HTMLElement {
|
|||
boolean reportValidity();
|
||||
undefined setCustomValidity(DOMString error);
|
||||
|
||||
// FIXME: readonly attribute NodeList labels;
|
||||
readonly attribute NodeList labels;
|
||||
|
||||
// FIXME: undefined select();
|
||||
attribute unsigned long selectionStart;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue