HTMLInputElement.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibWeb/DOM/Document.h>
  7. #include <LibWeb/DOM/Event.h>
  8. #include <LibWeb/DOM/ShadowRoot.h>
  9. #include <LibWeb/DOM/Text.h>
  10. #include <LibWeb/HTML/BrowsingContext.h>
  11. #include <LibWeb/HTML/EventNames.h>
  12. #include <LibWeb/HTML/HTMLFormElement.h>
  13. #include <LibWeb/HTML/HTMLInputElement.h>
  14. #include <LibWeb/Layout/BlockContainer.h>
  15. #include <LibWeb/Layout/ButtonBox.h>
  16. #include <LibWeb/Layout/CheckBox.h>
  17. #include <LibWeb/Layout/RadioButton.h>
  18. namespace Web::HTML {
  19. HTMLInputElement::HTMLInputElement(DOM::Document& document, QualifiedName qualified_name)
  20. : HTMLElement(document, move(qualified_name))
  21. {
  22. }
  23. HTMLInputElement::~HTMLInputElement()
  24. {
  25. }
  26. void HTMLInputElement::did_click_button(Badge<Layout::ButtonBox>)
  27. {
  28. // FIXME: This should be a PointerEvent.
  29. dispatch_event(DOM::Event::create(EventNames::click));
  30. if (type().equals_ignoring_case("submit")) {
  31. if (auto* form = first_ancestor_of_type<HTMLFormElement>()) {
  32. form->submit_form(this);
  33. }
  34. return;
  35. }
  36. }
  37. RefPtr<Layout::Node> HTMLInputElement::create_layout_node()
  38. {
  39. if (type() == "hidden")
  40. return nullptr;
  41. auto style = document().style_computer().compute_style(*this);
  42. if (style->display().is_none())
  43. return nullptr;
  44. if (type().equals_ignoring_case("submit") || type().equals_ignoring_case("button"))
  45. return adopt_ref(*new Layout::ButtonBox(document(), *this, move(style)));
  46. if (type() == "checkbox")
  47. return adopt_ref(*new Layout::CheckBox(document(), *this, move(style)));
  48. if (type() == "radio")
  49. return adopt_ref(*new Layout::RadioButton(document(), *this, move(style)));
  50. create_shadow_tree_if_needed();
  51. auto layout_node = adopt_ref(*new Layout::BlockContainer(document(), this, move(style)));
  52. layout_node->set_inline(true);
  53. return layout_node;
  54. }
  55. void HTMLInputElement::set_checked(bool checked)
  56. {
  57. if (m_checked == checked)
  58. return;
  59. m_checked = checked;
  60. if (layout_node())
  61. layout_node()->set_needs_display();
  62. dispatch_event(DOM::Event::create(EventNames::change));
  63. }
  64. bool HTMLInputElement::enabled() const
  65. {
  66. return !has_attribute(HTML::AttributeNames::disabled);
  67. }
  68. String HTMLInputElement::value() const
  69. {
  70. if (m_text_node)
  71. return m_text_node->data();
  72. return default_value();
  73. }
  74. void HTMLInputElement::set_value(String value)
  75. {
  76. if (m_text_node) {
  77. m_text_node->set_data(move(value));
  78. return;
  79. }
  80. set_attribute(HTML::AttributeNames::value, move(value));
  81. }
  82. void HTMLInputElement::create_shadow_tree_if_needed()
  83. {
  84. if (shadow_root())
  85. return;
  86. // FIXME: This assumes that we want a text box. Is that always true?
  87. auto shadow_root = adopt_ref(*new DOM::ShadowRoot(document(), *this));
  88. auto initial_value = attribute(HTML::AttributeNames::value);
  89. if (initial_value.is_null())
  90. initial_value = String::empty();
  91. auto element = document().create_element(HTML::TagNames::div);
  92. element->set_attribute(HTML::AttributeNames::style, "white-space: pre");
  93. m_text_node = adopt_ref(*new DOM::Text(document(), initial_value));
  94. m_text_node->set_always_editable(true);
  95. element->append_child(*m_text_node);
  96. shadow_root->append_child(move(element));
  97. set_shadow_root(move(shadow_root));
  98. }
  99. void HTMLInputElement::inserted()
  100. {
  101. HTMLElement::inserted();
  102. set_form(first_ancestor_of_type<HTMLFormElement>());
  103. }
  104. void HTMLInputElement::removed_from(DOM::Node* old_parent)
  105. {
  106. HTMLElement::removed_from(old_parent);
  107. set_form(nullptr);
  108. }
  109. }