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