mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 06:17:35 +00:00
LibWeb: Implement value attribute of RadioNodeList
This commit is contained in:
parent
708263790a
commit
f115e44066
5 changed files with 180 additions and 1 deletions
47
Tests/LibWeb/Text/expected/radio-node-list.txt
Normal file
47
Tests/LibWeb/Text/expected/radio-node-list.txt
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
value1 value2 ===================
|
||||||
|
non-checked-with-value
|
||||||
|
===================
|
||||||
|
2
|
||||||
|
value1
|
||||||
|
value2
|
||||||
|
value = ''
|
||||||
|
value = ''
|
||||||
|
===================
|
||||||
|
checked-with-value
|
||||||
|
===================
|
||||||
|
2
|
||||||
|
value3
|
||||||
|
value4
|
||||||
|
value = 'value3'
|
||||||
|
value = 'value3'
|
||||||
|
===================
|
||||||
|
checked-no-value
|
||||||
|
===================
|
||||||
|
2
|
||||||
|
on
|
||||||
|
on
|
||||||
|
value = 'on'
|
||||||
|
value = 'on'
|
||||||
|
===================
|
||||||
|
no-radio-button
|
||||||
|
===================
|
||||||
|
2
|
||||||
|
value1
|
||||||
|
value2
|
||||||
|
value = ''
|
||||||
|
value = ''
|
||||||
|
===================
|
||||||
|
non-checked-with-value
|
||||||
|
===================
|
||||||
|
value =
|
||||||
|
value = value1
|
||||||
|
===================
|
||||||
|
non-checked-no-value
|
||||||
|
===================
|
||||||
|
value =
|
||||||
|
value = on
|
||||||
|
===================
|
||||||
|
non-checked-value-on
|
||||||
|
===================
|
||||||
|
value =
|
||||||
|
value = on
|
52
Tests/LibWeb/Text/input/radio-node-list.html
Normal file
52
Tests/LibWeb/Text/input/radio-node-list.html
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
<form>
|
||||||
|
<input value="value1" id="non-checked-with-value" type="radio"/>
|
||||||
|
<input value="value2" id="non-checked-with-value" type="radio"/>
|
||||||
|
<input value="value3" id="checked-with-value" type="radio" checked/>
|
||||||
|
<input value="value4" id="checked-with-value" type="radio" checked/>
|
||||||
|
<input value="on" id="non-checked-value-on" type="radio"/>
|
||||||
|
<input value="on" id="non-checked-value-on" type="radio"/>
|
||||||
|
<input value="value1" id="no-radio-button" type="input" checked/>
|
||||||
|
<input value="value2" id="no-radio-button" type="input" checked/>
|
||||||
|
<input id="checked-no-value" type="radio" checked/>
|
||||||
|
<input id="checked-no-value" type="radio" checked/>
|
||||||
|
<input id="non-checked-no-value" type="radio"/>
|
||||||
|
<input id="non-checked-no-value" type="radio"/>
|
||||||
|
</form>
|
||||||
|
<script src="include.js"></script>
|
||||||
|
<script>
|
||||||
|
test(() => {
|
||||||
|
const formElements = document.forms[0].elements;
|
||||||
|
|
||||||
|
function dumpAttributes(name) {
|
||||||
|
println("===================");
|
||||||
|
println(name);
|
||||||
|
println("===================");
|
||||||
|
const list = formElements.namedItem(name);
|
||||||
|
println(list.length);
|
||||||
|
println(list[0].value);
|
||||||
|
println(list[1].value);
|
||||||
|
println(`value = '${list.value}'`);
|
||||||
|
list.value = "on";
|
||||||
|
println(`value = '${list.value}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setValue(name, value) {
|
||||||
|
println("===================");
|
||||||
|
println(name);
|
||||||
|
println("===================");
|
||||||
|
const list = formElements.namedItem(name);
|
||||||
|
println(`value = ${list.value}`);
|
||||||
|
list.value = value;
|
||||||
|
println(`value = ${list.value}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
dumpAttributes("non-checked-with-value");
|
||||||
|
dumpAttributes("checked-with-value");
|
||||||
|
dumpAttributes("checked-no-value");
|
||||||
|
dumpAttributes("no-radio-button");
|
||||||
|
|
||||||
|
setValue("non-checked-with-value", "value1")
|
||||||
|
setValue("non-checked-no-value", "on")
|
||||||
|
setValue("non-checked-value-on", "on")
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -8,6 +8,7 @@
|
||||||
#include <LibWeb/Bindings/RadioNodeListPrototype.h>
|
#include <LibWeb/Bindings/RadioNodeListPrototype.h>
|
||||||
#include <LibWeb/DOM/Element.h>
|
#include <LibWeb/DOM/Element.h>
|
||||||
#include <LibWeb/DOM/RadioNodeList.h>
|
#include <LibWeb/DOM/RadioNodeList.h>
|
||||||
|
#include <LibWeb/HTML/HTMLInputElement.h>
|
||||||
|
|
||||||
namespace Web::DOM {
|
namespace Web::DOM {
|
||||||
|
|
||||||
|
@ -29,4 +30,80 @@ void RadioNodeList::initialize(JS::Realm& realm)
|
||||||
set_prototype(&Bindings::ensure_web_prototype<Bindings::RadioNodeListPrototype>(realm, "RadioNodeList"));
|
set_prototype(&Bindings::ensure_web_prototype<Bindings::RadioNodeListPrototype>(realm, "RadioNodeList"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HTML::HTMLInputElement const* radio_button(Node const& node)
|
||||||
|
{
|
||||||
|
if (!is<HTML::HTMLInputElement>(node))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto const& input_element = verify_cast<HTML::HTMLInputElement>(node);
|
||||||
|
if (input_element.type_state() != HTML::HTMLInputElement::TypeAttributeState::RadioButton)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return &input_element;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#dom-radionodelist-value
|
||||||
|
FlyString RadioNodeList::value() const
|
||||||
|
{
|
||||||
|
// 1. Let element be the first element in tree order represented by the RadioNodeList object that is an input element whose type
|
||||||
|
// attribute is in the Radio Button state and whose checkedness is true. Otherwise, let it be null.
|
||||||
|
auto* element = verify_cast<HTML::HTMLInputElement>(first_matching([](Node const& node) -> bool {
|
||||||
|
auto const* button = radio_button(node);
|
||||||
|
if (!button)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return button->checked();
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 2. If element is null, return the empty string.
|
||||||
|
if (!element)
|
||||||
|
return String {};
|
||||||
|
|
||||||
|
// 3. If element is an element with no value attribute, return the string "on".
|
||||||
|
auto const value = element->get_attribute(HTML::AttributeNames::value);
|
||||||
|
if (value.is_null())
|
||||||
|
return "on"_fly_string;
|
||||||
|
|
||||||
|
// 4. Otherwise, return the value of element's value attribute.
|
||||||
|
return MUST(FlyString::from_deprecated_fly_string(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RadioNodeList::set_value(FlyString const& value)
|
||||||
|
{
|
||||||
|
HTML::HTMLInputElement* element = nullptr;
|
||||||
|
|
||||||
|
auto deprecated_value = value.to_deprecated_fly_string();
|
||||||
|
|
||||||
|
// 1. If the new value is the string "on": let element be the first element in tree order represented by the RadioNodeList object
|
||||||
|
// that is an input element whose type attribute is in the Radio Button state and whose value content attribute is either absent,
|
||||||
|
// or present and equal to the new value, if any. If no such element exists, then instead let element be null.
|
||||||
|
if (value == "on"sv) {
|
||||||
|
element = verify_cast<HTML::HTMLInputElement>(first_matching([&deprecated_value](auto const& node) {
|
||||||
|
auto const* button = radio_button(node);
|
||||||
|
if (!button)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto const value = button->get_attribute(HTML::AttributeNames::value);
|
||||||
|
return value.is_null() || value == deprecated_value;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
// 2. Otherwise: let element be the first element in tree order represented by the RadioNodeList object that is an input element whose
|
||||||
|
// type attribute is in the Radio Button state and whose value content attribute is present and equal to the new value, if any. If
|
||||||
|
// no such element exists, then instead let element be null.
|
||||||
|
else {
|
||||||
|
element = verify_cast<HTML::HTMLInputElement>(first_matching([&deprecated_value](auto const& node) {
|
||||||
|
auto const* button = radio_button(node);
|
||||||
|
if (!button)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto const value = button->get_attribute(HTML::AttributeNames::value);
|
||||||
|
return !value.is_null() && value == deprecated_value;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. If element is not null, then set its checkedness to true.
|
||||||
|
if (element)
|
||||||
|
element->set_checked(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,9 @@ public:
|
||||||
|
|
||||||
virtual ~RadioNodeList() override;
|
virtual ~RadioNodeList() override;
|
||||||
|
|
||||||
|
FlyString value() const;
|
||||||
|
void set_value(FlyString const&);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
|
|
||||||
|
|
|
@ -3,5 +3,5 @@
|
||||||
// https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#radionodelist
|
// https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#radionodelist
|
||||||
[Exposed=Window, UseNewAKString]
|
[Exposed=Window, UseNewAKString]
|
||||||
interface RadioNodeList : NodeList {
|
interface RadioNodeList : NodeList {
|
||||||
// FIXME: attribute DOMString value;
|
attribute DOMString value;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue