mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-30 12:49:19 +00:00
LibWeb: Implement the HTMLInputElement.list
attribute
This returns the `HTMLDataListElement` pointed to by the `list` content attribute.
This commit is contained in:
parent
a37315da87
commit
6178557a07
Notes:
github-actions[bot]
2025-03-09 15:11:49 +00:00
Author: https://github.com/tcl3
Commit: 6178557a07
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3782
7 changed files with 164 additions and 1 deletions
|
@ -32,6 +32,7 @@
|
||||||
#include <LibWeb/HTML/Dates.h>
|
#include <LibWeb/HTML/Dates.h>
|
||||||
#include <LibWeb/HTML/DecodedImageData.h>
|
#include <LibWeb/HTML/DecodedImageData.h>
|
||||||
#include <LibWeb/HTML/EventNames.h>
|
#include <LibWeb/HTML/EventNames.h>
|
||||||
|
#include <LibWeb/HTML/HTMLDataListElement.h>
|
||||||
#include <LibWeb/HTML/HTMLDivElement.h>
|
#include <LibWeb/HTML/HTMLDivElement.h>
|
||||||
#include <LibWeb/HTML/HTMLFormElement.h>
|
#include <LibWeb/HTML/HTMLFormElement.h>
|
||||||
#include <LibWeb/HTML/HTMLInputElement.h>
|
#include <LibWeb/HTML/HTMLInputElement.h>
|
||||||
|
@ -190,6 +191,39 @@ void HTMLInputElement::set_indeterminate(bool value)
|
||||||
m_indeterminate = value;
|
m_indeterminate = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/input.html#dom-input-list
|
||||||
|
GC::Ptr<HTMLDataListElement const> HTMLInputElement::list() const
|
||||||
|
{
|
||||||
|
// The list IDL attribute must return the current suggestions source element, if any, or null otherwise.
|
||||||
|
if (auto data_list_element = suggestions_source_element(); data_list_element.has_value())
|
||||||
|
return *data_list_element;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/input.html#concept-input-list
|
||||||
|
Optional<GC::Ref<HTMLDataListElement const>> HTMLInputElement::suggestions_source_element() const
|
||||||
|
{
|
||||||
|
// The suggestions source element is the first element in the tree in tree order to have an ID equal to the value of the list attribute,
|
||||||
|
// if that element is a datalist element. If there is no list attribute, or if there is no element with that ID,
|
||||||
|
// or if the first element with that ID is not a datalist element, then there is no suggestions source element.
|
||||||
|
Optional<GC::Ref<HTMLDataListElement const>> result;
|
||||||
|
if (auto list_attribute_value = get_attribute(HTML::AttributeNames::list); list_attribute_value.has_value()) {
|
||||||
|
root().for_each_in_inclusive_subtree_of_type<DOM::Element>([&](auto& element) {
|
||||||
|
if (element.id() == *list_attribute_value) {
|
||||||
|
if (auto data_list_element = as_if<HTMLDataListElement>(element))
|
||||||
|
result = *data_list_element;
|
||||||
|
|
||||||
|
return TraversalDecision::Break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TraversalDecision::Continue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#compiled-pattern-regular-expression
|
// https://html.spec.whatwg.org/multipage/input.html#compiled-pattern-regular-expression
|
||||||
Optional<Regex<ECMA262>> HTMLInputElement::compiled_pattern_regular_expression() const
|
Optional<Regex<ECMA262>> HTMLInputElement::compiled_pattern_regular_expression() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -106,6 +106,8 @@ public:
|
||||||
bool indeterminate() const { return m_indeterminate; }
|
bool indeterminate() const { return m_indeterminate; }
|
||||||
void set_indeterminate(bool);
|
void set_indeterminate(bool);
|
||||||
|
|
||||||
|
GC::Ptr<HTMLDataListElement const> list() const;
|
||||||
|
|
||||||
void did_pick_color(Optional<Color> picked_color, ColorPickerUpdateState state);
|
void did_pick_color(Optional<Color> picked_color, ColorPickerUpdateState state);
|
||||||
|
|
||||||
enum class MultipleHandling {
|
enum class MultipleHandling {
|
||||||
|
@ -356,6 +358,8 @@ private:
|
||||||
|
|
||||||
Optional<Regex<ECMA262>> compiled_pattern_regular_expression() const;
|
Optional<Regex<ECMA262>> compiled_pattern_regular_expression() const;
|
||||||
|
|
||||||
|
Optional<GC::Ref<HTMLDataListElement const>> suggestions_source_element() const;
|
||||||
|
|
||||||
Optional<DOM::DocumentLoadEventDelayer> m_load_event_delayer;
|
Optional<DOM::DocumentLoadEventDelayer> m_load_event_delayer;
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/input.html#dom-input-indeterminate
|
// https://html.spec.whatwg.org/multipage/input.html#dom-input-indeterminate
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#import <HTML/HTMLDataListElement.idl>
|
||||||
#import <HTML/HTMLElement.idl>
|
#import <HTML/HTMLElement.idl>
|
||||||
#import <HTML/HTMLFormElement.idl>
|
#import <HTML/HTMLFormElement.idl>
|
||||||
#import <HTML/PopoverInvokerElement.idl>
|
#import <HTML/PopoverInvokerElement.idl>
|
||||||
|
@ -25,7 +26,7 @@ interface HTMLInputElement : HTMLElement {
|
||||||
[CEReactions, Reflect=formtarget] attribute DOMString formTarget;
|
[CEReactions, Reflect=formtarget] attribute DOMString formTarget;
|
||||||
[CEReactions] attribute unsigned long height;
|
[CEReactions] attribute unsigned long height;
|
||||||
attribute boolean indeterminate;
|
attribute boolean indeterminate;
|
||||||
[FIXME] readonly attribute HTMLDataListElement? list;
|
readonly attribute HTMLDataListElement? list;
|
||||||
[CEReactions, Reflect] attribute DOMString max;
|
[CEReactions, Reflect] attribute DOMString max;
|
||||||
[CEReactions] attribute long maxLength;
|
[CEReactions] attribute long maxLength;
|
||||||
[CEReactions, Reflect] attribute DOMString min;
|
[CEReactions, Reflect] attribute DOMString min;
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Found 6 tests
|
||||||
|
|
||||||
|
6 Pass
|
||||||
|
Pass getting .list of input must return the datalist with that id
|
||||||
|
Pass getting .list of input must return null if it has no list attribute
|
||||||
|
Pass getting .list of input must return null if the list attribute is a non-datalist's id
|
||||||
|
Pass getting .list of input must return null if the list attribute is no element's id
|
||||||
|
Pass getting .list of input must return null if the list attribute is used in a non-datalist earlier than a datalist
|
||||||
|
Pass getting .list of input must return the datalist with that id even if a later non-datalist also has the id
|
|
@ -0,0 +1,7 @@
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Found 2 tests
|
||||||
|
|
||||||
|
2 Pass
|
||||||
|
Pass Input element's list attribute should point to the datalist element.
|
||||||
|
Pass Input element's list attribute should point to the datalist element in Shadow DOM.
|
|
@ -0,0 +1,67 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>input list attribute</title>
|
||||||
|
<script src="../../../../resources/testharness.js"></script>
|
||||||
|
<script src="../../../../resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
<h3>input_list</h3>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div id="log"></div>
|
||||||
|
|
||||||
|
<form method="post"
|
||||||
|
enctype="application/x-www-form-urlencoded"
|
||||||
|
action=""
|
||||||
|
name="input_form">
|
||||||
|
<datalist id="thelist">
|
||||||
|
<option value="one">one</option>
|
||||||
|
<option value="two">two</option>
|
||||||
|
</datalist>
|
||||||
|
|
||||||
|
<p id="non_datalist_first">
|
||||||
|
<datalist id="non_datalist_first">
|
||||||
|
<option value="one">one</option>
|
||||||
|
<option value="two">two</option>
|
||||||
|
</datalist>
|
||||||
|
|
||||||
|
<datalist id="datalist_first">
|
||||||
|
<option value="one">one</option>
|
||||||
|
<option value="two">two</option>
|
||||||
|
</datalist>
|
||||||
|
<p id="datalist_first">
|
||||||
|
|
||||||
|
<p><input list="thelist" id='input_with_list'></p>
|
||||||
|
<p><input id='input_without_list'></p>
|
||||||
|
<p><input list="input_with_list" id='input_with_nondatalist_list'></p>
|
||||||
|
<p><input list="not_an_id" id='input_with_missing_list'></p>
|
||||||
|
<p><input list="non_datalist_first" id='input_with_non_datalist_first'></p>
|
||||||
|
<p><input list="datalist_first" id='input_with_datalist_first'></p>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
assert_equals(document.getElementById("input_with_list").list, document.getElementById("thelist"));
|
||||||
|
}, "getting .list of input must return the datalist with that id");
|
||||||
|
test(function() {
|
||||||
|
assert_equals(document.getElementById("input_without_list").list, null);
|
||||||
|
}, "getting .list of input must return null if it has no list attribute");
|
||||||
|
test(function() {
|
||||||
|
assert_equals(document.getElementById("input_with_nondatalist_list").list, null);
|
||||||
|
}, "getting .list of input must return null if the list attribute is a non-datalist's id");
|
||||||
|
test(function() {
|
||||||
|
assert_equals(document.getElementById("input_with_missing_list").list, null);
|
||||||
|
}, "getting .list of input must return null if the list attribute is no element's id");
|
||||||
|
test(function() {
|
||||||
|
assert_equals(document.getElementById("input_with_non_datalist_first").list, null);
|
||||||
|
}, "getting .list of input must return null if the list attribute is used in a non-datalist earlier than a datalist");
|
||||||
|
test(function() {
|
||||||
|
assert_equals(document.getElementById("input_with_datalist_first").list, document.querySelector("datalist#datalist_first"));
|
||||||
|
}, "getting .list of input must return the datalist with that id even if a later non-datalist also has the id");
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Input.list</title>
|
||||||
|
<script src=../resources/testharness.js></script>
|
||||||
|
<script src=../resources/testharnessreport.js></script>
|
||||||
|
<div id="testcontent">
|
||||||
|
<input id="input" list="datalist">
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
assert_equals(document.getElementById('input').list, null);
|
||||||
|
var dl = document.createElement("datalist");
|
||||||
|
dl.id = "datalist";
|
||||||
|
document.getElementById("testcontent").appendChild(dl);
|
||||||
|
assert_equals(document.getElementById('input').list, dl);
|
||||||
|
}, "Input element's list attribute should point to the datalist element.");
|
||||||
|
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
var host = document.createElement("div");
|
||||||
|
document.getElementById("testcontent").appendChild(host);
|
||||||
|
var sr = host.attachShadow({mode: "open"});
|
||||||
|
var input = document.createElement("input");
|
||||||
|
input.setAttribute("list", "datalist");
|
||||||
|
sr.appendChild(input);
|
||||||
|
assert_equals(input.list, null);
|
||||||
|
|
||||||
|
var dl = document.createElement("datalist");
|
||||||
|
dl.id = "datalist";
|
||||||
|
sr.appendChild(dl);
|
||||||
|
assert_equals(input.list, dl);
|
||||||
|
|
||||||
|
dl.remove();
|
||||||
|
assert_equals(input.list, null);
|
||||||
|
}, "Input element's list attribute should point to the datalist element in Shadow DOM.");
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
Loading…
Add table
Add a link
Reference in a new issue