RadioNodeList.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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. auto const value = element->get_attribute(HTML::AttributeNames::value);
  51. if (value.is_null())
  52. return "on"_fly_string;
  53. // 4. Otherwise, return the value of element's value attribute.
  54. return MUST(FlyString::from_deprecated_fly_string(value));
  55. }
  56. void RadioNodeList::set_value(FlyString const& value)
  57. {
  58. HTML::HTMLInputElement* element = nullptr;
  59. auto deprecated_value = value.to_deprecated_fly_string();
  60. // 1. If the new value is the string "on": let element be the first element in tree order represented by the RadioNodeList object
  61. // that is an input element whose type attribute is in the Radio Button state and whose value content attribute is either absent,
  62. // or present and equal to the new value, if any. If no such element exists, then instead let element be null.
  63. if (value == "on"sv) {
  64. element = verify_cast<HTML::HTMLInputElement>(first_matching([&deprecated_value](auto const& node) {
  65. auto const* button = radio_button(node);
  66. if (!button)
  67. return false;
  68. auto const value = button->get_attribute(HTML::AttributeNames::value);
  69. return value.is_null() || value == deprecated_value;
  70. }));
  71. }
  72. // 2. Otherwise: let element be the first element in tree order represented by the RadioNodeList object that is an input element whose
  73. // type attribute is in the Radio Button state and whose value content attribute is present and equal to the new value, if any. If
  74. // no such element exists, then instead let element be null.
  75. else {
  76. element = verify_cast<HTML::HTMLInputElement>(first_matching([&deprecated_value](auto const& node) {
  77. auto const* button = radio_button(node);
  78. if (!button)
  79. return false;
  80. auto const value = button->get_attribute(HTML::AttributeNames::value);
  81. return !value.is_null() && value == deprecated_value;
  82. }));
  83. }
  84. // 3. If element is not null, then set its checkedness to true.
  85. if (element)
  86. element->set_checked(true);
  87. }
  88. }