/* * Copyright (c) 2018-2021, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include #include #include #include #include #include namespace Web::HTML { HTMLInputElement::HTMLInputElement(DOM::Document& document, QualifiedName qualified_name) : FormAssociatedElement(document, move(qualified_name)) { } HTMLInputElement::~HTMLInputElement() { } void HTMLInputElement::did_click_button(Badge) { // FIXME: This should be a PointerEvent. dispatch_event(DOM::Event::create(EventNames::click)); if (type().equals_ignoring_case("submit")) { if (auto* form = first_ancestor_of_type()) { form->submit_form(this); } return; } } RefPtr HTMLInputElement::create_layout_node(NonnullRefPtr style) { if (type() == "hidden") return nullptr; if (type().equals_ignoring_case("submit") || type().equals_ignoring_case("button")) return adopt_ref(*new Layout::ButtonBox(document(), *this, move(style))); if (type() == "checkbox") return adopt_ref(*new Layout::CheckBox(document(), *this, move(style))); if (type() == "radio") return adopt_ref(*new Layout::RadioButton(document(), *this, move(style))); create_shadow_tree_if_needed(); auto layout_node = adopt_ref(*new Layout::BlockContainer(document(), this, move(style))); layout_node->set_inline(true); return layout_node; } void HTMLInputElement::set_checked(bool checked) { if (m_checked == checked) return; m_checked = checked; if (layout_node()) layout_node()->set_needs_display(); dispatch_event(DOM::Event::create(EventNames::change)); } bool HTMLInputElement::enabled() const { return !has_attribute(HTML::AttributeNames::disabled); } String HTMLInputElement::value() const { if (m_text_node) return m_text_node->data(); return default_value(); } void HTMLInputElement::set_value(String value) { if (m_text_node) { m_text_node->set_data(move(value)); return; } set_attribute(HTML::AttributeNames::value, move(value)); } void HTMLInputElement::create_shadow_tree_if_needed() { if (shadow_root()) return; // FIXME: This assumes that we want a text box. Is that always true? auto shadow_root = adopt_ref(*new DOM::ShadowRoot(document(), *this)); auto initial_value = attribute(HTML::AttributeNames::value); if (initial_value.is_null()) initial_value = String::empty(); auto element = document().create_element(HTML::TagNames::div); element->set_attribute(HTML::AttributeNames::style, "white-space: pre"); m_text_node = adopt_ref(*new DOM::Text(document(), initial_value)); m_text_node->set_always_editable(true); element->append_child(*m_text_node); shadow_root->append_child(move(element)); set_shadow_root(move(shadow_root)); } void HTMLInputElement::did_receive_focus() { auto* browsing_context = document().browsing_context(); if (!browsing_context) return; if (!m_text_node) return; browsing_context->set_cursor_position(DOM::Position { *m_text_node, 0 }); } bool HTMLInputElement::is_focusable() const { return m_text_node; } void HTMLInputElement::inserted() { HTMLElement::inserted(); set_form(first_ancestor_of_type()); } void HTMLInputElement::removed_from(DOM::Node* old_parent) { HTMLElement::removed_from(old_parent); set_form(nullptr); } }