RadioNodeList.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * Copyright (c) 2023, Shannon Booth <shannon@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibWeb/Bindings/Intrinsics.h>
  7. #include <LibWeb/Bindings/RadioNodeListPrototype.h>
  8. #include <LibWeb/DOM/Element.h>
  9. #include <LibWeb/DOM/RadioNodeList.h>
  10. #include <LibWeb/HTML/HTMLInputElement.h>
  11. namespace Web::DOM {
  12. JS::NonnullGCPtr<RadioNodeList> RadioNodeList::create(JS::Realm& realm, Node& root, Scope scope, Function<bool(Node const&)> filter)
  13. {
  14. return realm.heap().allocate<RadioNodeList>(realm, realm, root, scope, move(filter));
  15. }
  16. RadioNodeList::RadioNodeList(JS::Realm& realm, Node& root, Scope scope, Function<bool(Node const&)> filter)
  17. : LiveNodeList(realm, root, scope, move(filter))
  18. {
  19. }
  20. RadioNodeList::~RadioNodeList() = default;
  21. void RadioNodeList::initialize(JS::Realm& realm)
  22. {
  23. Base::initialize(realm);
  24. set_prototype(&Bindings::ensure_web_prototype<Bindings::RadioNodeListPrototype>(realm, "RadioNodeList"));
  25. }
  26. static HTML::HTMLInputElement const* radio_button(Node const& node)
  27. {
  28. if (!is<HTML::HTMLInputElement>(node))
  29. return nullptr;
  30. auto const& input_element = verify_cast<HTML::HTMLInputElement>(node);
  31. if (input_element.type_state() != HTML::HTMLInputElement::TypeAttributeState::RadioButton)
  32. return nullptr;
  33. return &input_element;
  34. }
  35. // https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#dom-radionodelist-value
  36. FlyString RadioNodeList::value() const
  37. {
  38. // 1. Let element be the first element in tree order represented by the RadioNodeList object that is an input element whose type
  39. // attribute is in the Radio Button state and whose checkedness is true. Otherwise, let it be null.
  40. auto* element = verify_cast<HTML::HTMLInputElement>(first_matching([](Node const& node) -> bool {
  41. auto const* button = radio_button(node);
  42. if (!button)
  43. return false;
  44. return button->checked();
  45. }));
  46. // 2. If element is null, return the empty string.
  47. if (!element)
  48. return String {};
  49. // 3. If element is an element with no value attribute, return the string "on".
  50. // 4. Otherwise, return the value of element's value attribute.
  51. return element->get_attribute(HTML::AttributeNames::value).value_or("on"_string);
  52. }
  53. void RadioNodeList::set_value(FlyString const& value)
  54. {
  55. HTML::HTMLInputElement* element = nullptr;
  56. // 1. If the new value is the string "on": let element be the first element in tree order represented by the RadioNodeList object
  57. // that is an input element whose type attribute is in the Radio Button state and whose value content attribute is either absent,
  58. // or present and equal to the new value, if any. If no such element exists, then instead let element be null.
  59. if (value == "on"sv) {
  60. element = verify_cast<HTML::HTMLInputElement>(first_matching([&value](auto const& node) {
  61. auto const* button = radio_button(node);
  62. if (!button)
  63. return false;
  64. auto const maybe_value = button->get_attribute(HTML::AttributeNames::value);
  65. return !maybe_value.has_value() || maybe_value.value() == value;
  66. }));
  67. }
  68. // 2. Otherwise: let element be the first element in tree order represented by the RadioNodeList object that is an input element whose
  69. // type attribute is in the Radio Button state and whose value content attribute is present and equal to the new value, if any. If
  70. // no such element exists, then instead let element be null.
  71. else {
  72. element = verify_cast<HTML::HTMLInputElement>(first_matching([&value](auto const& node) {
  73. auto const* button = radio_button(node);
  74. if (!button)
  75. return false;
  76. auto const maybe_value = button->get_attribute(HTML::AttributeNames::value);
  77. return maybe_value.has_value() && maybe_value.value() == value;
  78. }));
  79. }
  80. // 3. If element is not null, then set its checkedness to true.
  81. if (element)
  82. element->set_checked(true);
  83. }
  84. }