LibWeb: Follow spec steps to set the selectionDirection attribute value

This commit is contained in:
Tim Ledbetter 2024-10-04 12:12:39 +01:00 committed by Andreas Kling
commit d0b97873d4
Notes: github-actions[bot] 2024-10-04 17:43:25 +00:00
10 changed files with 68 additions and 4 deletions

View file

@ -15,4 +15,5 @@ select event fired: 6 6
text-input selectionStart: 6 selectionEnd: 6 selectionDirection: forward
select event fired: 6 6
text-input selectionStart: 6 selectionEnd: 6 selectionDirection: backward
select event fired: 6 6
textarea selectionStart: 0 selectionEnd: 9 selectionDirection: none

View file

@ -0,0 +1,2 @@
select event fired for input
select event fired for textarea

View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<script src="../include.js"></script>
<script>
asyncTest(done => {
const elementNames = [
"input",
"textarea",
];
let selectEventFiredCount = 0;
for (const elementName of elementNames) {
const element = document.createElement(elementName);
element.setRangeText("foobar", 0, element.value.length, "start");
document.body.appendChild(element);
element.onselect = () => {
element.remove();
println(`select event fired for ${elementName}`);
selectEventFiredCount++;
if (selectEventFiredCount === elementNames.length) {
done();
}
};
element.selectionDirection = "backward";
}
});
</script>

View file

@ -366,6 +366,22 @@ void FormAssociatedTextControlElement::set_selection_direction(Optional<String>
m_selection_direction = string_to_selection_direction(direction);
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-selectiondirection
WebIDL::ExceptionOr<void> FormAssociatedTextControlElement::set_selection_direction_binding(Optional<String> direction)
{
// 1. If this element is an input element, and selectionDirection does not apply to this element,
// throw an "InvalidStateError" DOMException.
auto const& html_element = form_associated_element_to_html_element();
if (is<HTMLInputElement>(html_element)) {
auto const& input_element = static_cast<HTMLInputElement const&>(html_element);
if (!input_element.selection_direction_applies())
return WebIDL::InvalidStateError::create(input_element.realm(), "selectionDirection does not apply to element"_fly_string);
}
set_the_selection_range(m_selection_start, m_selection_end, string_to_selection_direction(direction));
return {};
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-setrangetext
WebIDL::ExceptionOr<void> FormAssociatedTextControlElement::set_range_text(String const& replacement)
{

View file

@ -149,6 +149,7 @@ public:
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-selectiondirection
Optional<String> selection_direction() const;
void set_selection_direction(Optional<String> direction);
WebIDL::ExceptionOr<void> set_selection_direction_binding(Optional<String> direction);
SelectionDirection selection_direction_state() const { return m_selection_direction; }
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-setrangetext

View file

@ -2359,6 +2359,21 @@ bool HTMLInputElement::selection_or_range_applies() const
return selection_or_range_applies_for_type_state(type_state());
}
// https://html.spec.whatwg.org/multipage/input.html#do-not-apply
bool HTMLInputElement::selection_direction_applies() const
{
switch (type_state()) {
case TypeAttributeState::Text:
case TypeAttributeState::Search:
case TypeAttributeState::Telephone:
case TypeAttributeState::URL:
case TypeAttributeState::Password:
return true;
default:
return false;
}
}
bool HTMLInputElement::has_selectable_text() const
{
// Potential FIXME: Date, Month, Week, Time and LocalDateAndTime are rendered as a basic text input for now,

View file

@ -204,10 +204,13 @@ public:
bool step_up_or_down_applies() const;
bool select_applies() const;
bool selection_or_range_applies() const;
bool selection_direction_applies() const;
bool has_selectable_text() const;
static bool selection_or_range_applies_for_type_state(TypeAttributeState);
Optional<String> selection_direction_binding() { return selection_direction(); }
protected:
void selection_was_changed(size_t selection_start, size_t selection_end) override;

View file

@ -60,7 +60,7 @@ interface HTMLInputElement : HTMLElement {
undefined select();
attribute unsigned long? selectionStart;
attribute unsigned long? selectionEnd;
attribute DOMString? selectionDirection;
[ImplementedAs=selection_direction_binding] attribute DOMString? selectionDirection;
undefined setRangeText(DOMString replacement);
undefined setRangeText(DOMString replacement, unsigned long start, unsigned long end, optional SelectionMode selectionMode = "preserve");
undefined setSelectionRange(unsigned long start, unsigned long end, optional DOMString direction);

View file

@ -329,9 +329,10 @@ String HTMLTextAreaElement::selection_direction_binding() const
return selection_direction().value();
}
void HTMLTextAreaElement::set_selection_direction_binding(String direction)
void HTMLTextAreaElement::set_selection_direction_binding(String const& direction)
{
set_selection_direction(direction);
// NOTE: The selectionDirection setter never returns an error for textarea elements.
MUST(static_cast<FormAssociatedTextControlElement&>(*this).set_selection_direction_binding(direction));
}
void HTMLTextAreaElement::create_shadow_tree_if_needed()

View file

@ -118,7 +118,7 @@ public:
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-selectiondirection
String selection_direction_binding() const;
void set_selection_direction_binding(String direction);
void set_selection_direction_binding(String const& direction);
void set_dirty_value_flag(Badge<FormAssociatedElement>, bool flag) { m_dirty_value = flag; }