LibWeb: Partially implement <textarea>'s selectionStart and selectionEnd

This implementation pretends we never have a selection. GitHub relies on
these values to know where to insert text corresponding to file uploads.
This commit is contained in:
Timothy Flynn 2024-03-14 10:05:07 -04:00 committed by Andreas Kling
parent abc1be5b9e
commit c0d594568d
5 changed files with 84 additions and 2 deletions

View file

@ -0,0 +1,4 @@
Well hello friends selectionStart: 0
selectionEnd: 0
selectionStart: 18
selectionEnd: 18

View file

@ -0,0 +1,15 @@
<textarea id="textarea"></textarea>
<script src="include.js"></script>
<script type="text/javascript">
test(() => {
let textarea = document.getElementById("textarea");
textarea.focus();
println(`selectionStart: ${textarea.selectionStart}`);
println(`selectionEnd: ${textarea.selectionEnd}`);
textarea.value = "Well hello friends";
println(`selectionStart: ${textarea.selectionStart}`);
println(`selectionEnd: ${textarea.selectionEnd}`);
});
</script>

View file

@ -201,6 +201,63 @@ void HTMLTextAreaElement::set_custom_validity(String const& error)
dbgln("(STUBBED) HTMLTextAreaElement::set_custom_validity(\"{}\"). Called on: {}", error, debug_description());
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-selectionstart
WebIDL::UnsignedLong HTMLTextAreaElement::selection_start() const
{
// 1. If this element is an input element, and selectionStart does not apply to this element, return null.
// 2. If there is no selection, return the code unit offset within the relevant value to the character that
// immediately follows the text entry cursor.
if (auto const* browsing_context = document().browsing_context()) {
if (auto cursor = browsing_context->cursor_position())
return cursor->offset();
}
// FIXME: 3. Return the code unit offset within the relevant value to the character that immediately follows the start of
// the selection.
return 0;
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#textFieldSelection:dom-textarea/input-selectionstart-2
WebIDL::ExceptionOr<void> HTMLTextAreaElement::set_selection_start(WebIDL::UnsignedLong)
{
// 1. If this element is an input element, and selectionStart does not apply to this element, throw an
// "InvalidStateError" DOMException.
// FIXME: 2. Let end be the value of this element's selectionEnd attribute.
// FIXME: 3. If end is less than the given value, set end to the given value.
// FIXME: 4. Set the selection range with the given value, end, and the value of this element's selectionDirection attribute.
return {};
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-selectionend
WebIDL::UnsignedLong HTMLTextAreaElement::selection_end() const
{
// 1. If this element is an input element, and selectionEnd does not apply to this element, return null.
// 2. If there is no selection, return the code unit offset within the relevant value to the character that
// immediately follows the text entry cursor.
if (auto const* browsing_context = document().browsing_context()) {
if (auto cursor = browsing_context->cursor_position())
return cursor->offset();
}
// FIXME: 3. Return the code unit offset within the relevant value to the character that immediately follows the end of
// the selection.
return 0;
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#textFieldSelection:dom-textarea/input-selectionend-3
WebIDL::ExceptionOr<void> HTMLTextAreaElement::set_selection_end(WebIDL::UnsignedLong)
{
// 1. If this element is an input element, and selectionEnd does not apply to this element, throw an
// "InvalidStateError" DOMException.
// FIXME: 2. Set the selection range with the value of this element's selectionStart attribute, the given value, and the
// value of this element's selectionDirection attribute.
return {};
}
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-textarea-maxlength
WebIDL::Long HTMLTextAreaElement::max_length() const
{

View file

@ -84,6 +84,12 @@ public:
bool report_validity();
void set_custom_validity(String const& error);
WebIDL::UnsignedLong selection_start() const;
WebIDL::ExceptionOr<void> set_selection_start(WebIDL::UnsignedLong);
WebIDL::UnsignedLong selection_end() const;
WebIDL::ExceptionOr<void> set_selection_end(WebIDL::UnsignedLong);
WebIDL::Long max_length() const;
WebIDL::ExceptionOr<void> set_max_length(WebIDL::Long);

View file

@ -35,8 +35,8 @@ interface HTMLTextAreaElement : HTMLElement {
// FIXME: readonly attribute NodeList labels;
// FIXME: undefined select();
// FIXME: attribute unsigned long selectionStart;
// FIXME: attribute unsigned long selectionEnd;
attribute unsigned long selectionStart;
attribute unsigned long selectionEnd;
// FIXME: attribute DOMString selectionDirection;
// FIXME: undefined setRangeText(DOMString replacement);
// FIXME: undefined setRangeText(DOMString replacement, unsigned long start, unsigned long end, optional SelectionMode selectionMode = "preserve");