Serenity Operating System
1/*
2 * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
3 * Copyright (c) 2022, Adam Hodgen <ant1441@gmail.com>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#pragma once
9
10#include <LibWeb/FileAPI/FileList.h>
11#include <LibWeb/HTML/FormAssociatedElement.h>
12#include <LibWeb/HTML/HTMLElement.h>
13#include <LibWeb/WebIDL/DOMException.h>
14
15namespace Web::HTML {
16
17// https://html.spec.whatwg.org/multipage/input.html#attr-input-type
18#define ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTES \
19 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(hidden, Hidden) \
20 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(text, Text) \
21 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(search, Search) \
22 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(tel, Telephone) \
23 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(url, URL) \
24 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(email, Email) \
25 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(password, Password) \
26 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(date, Date) \
27 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(month, Month) \
28 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(week, Week) \
29 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(time, Time) \
30 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE("datetime-local", LocalDateAndTime) \
31 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(number, Number) \
32 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(range, Range) \
33 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(color, Color) \
34 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(checkbox, Checkbox) \
35 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(radio, RadioButton) \
36 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(file, FileUpload) \
37 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(submit, SubmitButton) \
38 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(image, ImageButton) \
39 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(reset, ResetButton) \
40 __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(button, Button)
41
42class HTMLInputElement final
43 : public HTMLElement
44 , public FormAssociatedElement {
45 WEB_PLATFORM_OBJECT(HTMLInputElement, HTMLElement);
46 FORM_ASSOCIATED_ELEMENT(HTMLElement, HTMLInputElement)
47
48public:
49 virtual ~HTMLInputElement() override;
50
51 virtual JS::GCPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
52
53 enum class TypeAttributeState {
54#define __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(_, state) state,
55 ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTES
56#undef __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE
57 };
58
59 DeprecatedString type() const;
60 TypeAttributeState type_state() const { return m_type; }
61 void set_type(DeprecatedString const&);
62
63 DeprecatedString default_value() const { return attribute(HTML::AttributeNames::value); }
64 DeprecatedString name() const { return attribute(HTML::AttributeNames::name); }
65
66 DeprecatedString value() const;
67 WebIDL::ExceptionOr<void> set_value(DeprecatedString);
68
69 Optional<DeprecatedString> placeholder_value() const;
70
71 bool checked() const { return m_checked; }
72 enum class ChangeSource {
73 Programmatic,
74 User,
75 };
76 void set_checked(bool, ChangeSource = ChangeSource::Programmatic);
77
78 bool checked_binding() const { return checked(); }
79 void set_checked_binding(bool);
80
81 void did_edit_text_node(Badge<BrowsingContext>);
82
83 JS::GCPtr<FileAPI::FileList> files();
84 void set_files(JS::GCPtr<FileAPI::FileList>);
85
86 // NOTE: User interaction
87 // https://html.spec.whatwg.org/multipage/input.html#update-the-file-selection
88 void update_the_file_selection(JS::NonnullGCPtr<FileAPI::FileList>);
89
90 WebIDL::ExceptionOr<void> set_selection_range(u32 start, u32 end, DeprecatedString const& direction);
91
92 WebIDL::ExceptionOr<void> show_picker();
93
94 // ^EventTarget
95 // https://html.spec.whatwg.org/multipage/interaction.html#the-tabindex-attribute:the-input-element
96 virtual bool is_focusable() const override { return m_type != TypeAttributeState::Hidden; }
97
98 // ^HTMLElement
99 virtual void parse_attribute(DeprecatedFlyString const&, DeprecatedString const&) override;
100 virtual void did_remove_attribute(DeprecatedFlyString const&) override;
101
102 // ^FormAssociatedElement
103 // https://html.spec.whatwg.org/multipage/forms.html#category-listed
104 virtual bool is_listed() const override { return true; }
105
106 // https://html.spec.whatwg.org/multipage/forms.html#category-submit
107 virtual bool is_submittable() const override { return true; }
108
109 // https://html.spec.whatwg.org/multipage/forms.html#category-reset
110 virtual bool is_resettable() const override { return true; }
111
112 // https://html.spec.whatwg.org/multipage/forms.html#category-autocapitalize
113 virtual bool is_auto_capitalize_inheriting() const override { return true; }
114
115 virtual void reset_algorithm() override;
116
117 virtual void form_associated_element_was_inserted() override;
118
119 // ^HTMLElement
120 // https://html.spec.whatwg.org/multipage/forms.html#category-label
121 virtual bool is_labelable() const override { return type_state() != TypeAttributeState::Hidden; }
122
123 virtual Optional<ARIA::Role> default_role() const override;
124
125private:
126 HTMLInputElement(DOM::Document&, DOM::QualifiedName);
127
128 // ^DOM::Node
129 virtual bool is_html_input_element() const final { return true; }
130
131 // ^DOM::EventTarget
132 virtual void did_receive_focus() override;
133 virtual void legacy_pre_activation_behavior() override;
134 virtual void legacy_cancelled_activation_behavior() override;
135 virtual void legacy_cancelled_activation_behavior_was_not_called() override;
136
137 // ^DOM::Element
138 virtual i32 default_tab_index_value() const override;
139
140 virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
141 virtual void visit_edges(Cell::Visitor&) override;
142
143 static TypeAttributeState parse_type_attribute(StringView);
144 void create_shadow_tree_if_needed();
145 ErrorOr<void> run_input_activation_behavior();
146 void set_checked_within_group();
147
148 // https://html.spec.whatwg.org/multipage/input.html#value-sanitization-algorithm
149 DeprecatedString value_sanitization_algorithm(DeprecatedString) const;
150
151 JS::GCPtr<DOM::Text> m_text_node;
152 bool m_checked { false };
153
154 // https://html.spec.whatwg.org/multipage/input.html#concept-input-checked-dirty-flag
155 bool m_dirty_checkedness { false };
156
157 // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-fe-dirty
158 bool m_dirty_value { false };
159
160 // https://html.spec.whatwg.org/multipage/input.html#the-input-element:legacy-pre-activation-behavior
161 bool m_before_legacy_pre_activation_behavior_checked { false };
162 JS::GCPtr<HTMLInputElement> m_legacy_pre_activation_behavior_checked_element_in_group;
163
164 // https://html.spec.whatwg.org/multipage/input.html#concept-input-type-file-selected
165 JS::GCPtr<FileAPI::FileList> m_selected_files;
166
167 TypeAttributeState m_type { TypeAttributeState::Text };
168 DeprecatedString m_value;
169};
170
171}
172
173namespace Web::DOM {
174template<>
175inline bool Node::fast_is<HTML::HTMLInputElement>() const { return is_html_input_element(); }
176}