diff --git a/Tests/LibWeb/Text/expected/Editing/input-into-empty-contenteditable.txt b/Tests/LibWeb/Text/expected/Editing/input-into-empty-contenteditable.txt
new file mode 100644
index 0000000000..c867320453
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/Editing/input-into-empty-contenteditable.txt
@@ -0,0 +1 @@
+hello
diff --git a/Tests/LibWeb/Text/input/Editing/input-into-empty-contenteditable.html b/Tests/LibWeb/Text/input/Editing/input-into-empty-contenteditable.html
new file mode 100644
index 0000000000..c630401ea1
--- /dev/null
+++ b/Tests/LibWeb/Text/input/Editing/input-into-empty-contenteditable.html
@@ -0,0 +1,15 @@
+
+
+
+
diff --git a/Userland/Libraries/LibWeb/DOM/Position.h b/Userland/Libraries/LibWeb/DOM/Position.h
index c7b021decd..e1466d0d76 100644
--- a/Userland/Libraries/LibWeb/DOM/Position.h
+++ b/Userland/Libraries/LibWeb/DOM/Position.h
@@ -28,6 +28,7 @@ public:
JS::GCPtr node() { return m_node; }
JS::GCPtr node() const { return m_node; }
+ void set_node(JS::NonnullGCPtr node) { m_node = node; }
unsigned offset() const { return m_offset; }
bool offset_is_at_end_of_node() const;
diff --git a/Userland/Libraries/LibWeb/Page/EditEventHandler.cpp b/Userland/Libraries/LibWeb/Page/EditEventHandler.cpp
index 2d4acc1421..9dfe950c00 100644
--- a/Userland/Libraries/LibWeb/Page/EditEventHandler.cpp
+++ b/Userland/Libraries/LibWeb/Page/EditEventHandler.cpp
@@ -114,6 +114,15 @@ void EditEventHandler::handle_insert(JS::NonnullGCPtr position, u
node.set_data(MUST(builder.to_string()));
node.invalidate_style();
+ } else {
+ auto& node = *position->node();
+ auto& realm = node.realm();
+ StringBuilder builder;
+ builder.append_code_point(code_point);
+ auto text = realm.heap().allocate(realm, node.document(), MUST(builder.to_string()));
+ MUST(node.append_child(*text));
+ position->set_node(text);
+ position->set_offset(1);
}
// FIXME: When nodes are removed from the DOM, the associated layout nodes become stale and still
diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp
index 884eaef94b..87bba02d69 100644
--- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp
+++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp
@@ -787,8 +787,6 @@ bool EventHandler::handle_keydown(KeyCode key, u32 modifiers, u32 code_point)
return false;
if (m_browsing_context->cursor_position() && m_browsing_context->cursor_position()->node()->is_editable()) {
- auto& node = verify_cast(*m_browsing_context->cursor_position()->node());
-
if (key == KeyCode::Key_Backspace) {
if (!m_browsing_context->decrement_cursor_position_offset()) {
// FIXME: Move to the previous node and delete the last character there.
@@ -819,23 +817,37 @@ bool EventHandler::handle_keydown(KeyCode key, u32 modifiers, u32 code_point)
return true;
}
if (key == KeyCode::Key_Home) {
- m_browsing_context->set_cursor_position(DOM::Position::create(realm, node, 0));
+ auto& cursor_position_node = *m_browsing_context->cursor_position()->node();
+ if (cursor_position_node.is_text())
+ m_browsing_context->set_cursor_position(DOM::Position::create(realm, cursor_position_node, 0));
return true;
}
if (key == KeyCode::Key_End) {
- m_browsing_context->set_cursor_position(DOM::Position::create(realm, node, (unsigned)node.data().bytes().size()));
+ auto& cursor_position_node = *m_browsing_context->cursor_position()->node();
+ if (cursor_position_node.is_text()) {
+ auto& text_node = static_cast(cursor_position_node);
+ m_browsing_context->set_cursor_position(DOM::Position::create(realm, text_node, (unsigned)text_node.data().bytes().size()));
+ }
return true;
}
if (key == KeyCode::Key_Return) {
- if (is(node.editable_text_node_owner())) {
- auto& input_element = static_cast(*node.editable_text_node_owner());
-
- if (auto* form = input_element.form()) {
+ HTML::HTMLInputElement* input_element = nullptr;
+ if (auto node = m_browsing_context->cursor_position()->node()) {
+ if (node->is_text()) {
+ auto& text_node = static_cast(*node);
+ if (is(text_node.editable_text_node_owner()))
+ input_element = static_cast(text_node.editable_text_node_owner());
+ } else if (node->is_html_input_element()) {
+ input_element = static_cast(node.ptr());
+ }
+ }
+ if (input_element) {
+ if (auto* form = input_element->form()) {
form->implicitly_submit_form().release_value_but_fixme_should_propagate_errors();
return true;
}
- input_element.commit_pending_changes();
+ input_element->commit_pending_changes();
return true;
}
}