RadioNodeList.cpp 4.0 KB

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