From 7372c017863a1ec791d5b0c63b0cb7671d36ffaa Mon Sep 17 00:00:00 2001 From: Bastiaan van der Plaat Date: Mon, 8 Apr 2024 21:56:33 +0200 Subject: [PATCH] LibWeb: Add select and options collection remove method --- Tests/LibWeb/Text/expected/select.txt | 2 ++ Tests/LibWeb/Text/input/select.html | 22 +++++++++++++++++++ .../LibWeb/HTML/HTMLOptionsCollection.cpp | 18 +++++++++++++++ .../LibWeb/HTML/HTMLOptionsCollection.h | 2 ++ .../LibWeb/HTML/HTMLOptionsCollection.idl | 2 +- .../LibWeb/HTML/HTMLSelectElement.cpp | 13 +++++++++++ .../Libraries/LibWeb/HTML/HTMLSelectElement.h | 2 ++ .../LibWeb/HTML/HTMLSelectElement.idl | 4 ++-- 8 files changed, 62 insertions(+), 3 deletions(-) diff --git a/Tests/LibWeb/Text/expected/select.txt b/Tests/LibWeb/Text/expected/select.txt index 1404c3b63b5..93409b847f5 100644 --- a/Tests/LibWeb/Text/expected/select.txt +++ b/Tests/LibWeb/Text/expected/select.txt @@ -12,3 +12,5 @@ 12. 10 13. 10 14. "5 5" +15. 8 +16. 10 diff --git a/Tests/LibWeb/Text/input/select.html b/Tests/LibWeb/Text/input/select.html index c3d35eaa839..a6a24bd786f 100644 --- a/Tests/LibWeb/Text/input/select.html +++ b/Tests/LibWeb/Text/input/select.html @@ -146,5 +146,27 @@ } return `${select.options.selectedIndex} ${select.selectedIndex}`; }); + + // 15. Remove select options + testPart(() => { + const select = document.createElement('select'); + for (let i = 0; i < 10; i++) { + select.appendChild(document.createElement('option')); + } + select.remove(5); + select.options.remove(6); + return select.length; + }); + + // 16. Remove select options invalid + testPart(() => { + const select = document.createElement('select'); + for (let i = 0; i < 10; i++) { + select.appendChild(document.createElement('option')); + } + select.remove(-1); + select.options.remove(11); + return select.length; + }); }); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp index d09a41edf02..e4e16ce9da3 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp @@ -111,6 +111,24 @@ WebIDL::ExceptionOr HTMLOptionsCollection::add(HTMLOptionOrOptGroupElement return {}; } +// https://html.spec.whatwg.org/#dom-htmloptionscollection-remove +void HTMLOptionsCollection::remove(WebIDL::Long index) +{ + // 1. If the number of nodes represented by the collection is zero, return. + if (length() == 0) + return; + + // 2. If index is not a number greater than or equal to 0 and less than the number of nodes represented by the collection, return. + if (index < 0 || static_cast(index) >= length()) + return; + + // 3. Let element be the indexth element in the collection. + auto* element = this->item(index); + + // 4. Remove element from its parent node. + element->remove(); +} + // https://html.spec.whatwg.org/#dom-htmloptionscollection-selectedindex WebIDL::Long HTMLOptionsCollection::selected_index() const { diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.h b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.h index ac3bf39ce3e..abb8b46435e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.h @@ -28,6 +28,8 @@ public: WebIDL::ExceptionOr add(HTMLOptionOrOptGroupElement element, Optional before = {}); + void remove(WebIDL::Long); + WebIDL::Long selected_index() const; void set_selected_index(WebIDL::Long); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.idl b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.idl index 9ba14300167..ce09654e2a4 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.idl +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.idl @@ -8,6 +8,6 @@ interface HTMLOptionsCollection : HTMLCollection { [CEReactions] attribute unsigned long length; // shadows inherited length // [CEReactions] setter undefined (unsigned long index, HTMLOptionElement? option); [CEReactions] undefined add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null); - // [CEReactions] undefined remove(long index); + [CEReactions] undefined remove(long index); attribute long selectedIndex; }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp index 8f2f2d830b9..b1a16e40338 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp @@ -133,6 +133,19 @@ WebIDL::ExceptionOr HTMLSelectElement::add(HTMLOptionOrOptGroupElement ele return const_cast(*options()).add(move(element), move(before)); } +// https://html.spec.whatwg.org/multipage/form-elements.html#dom-select-remove +void HTMLSelectElement::remove() +{ + // The remove() method must act like its namesake method on that same options collection when it has arguments, + // and like its namesake method on the ChildNode interface implemented by the HTMLSelectElement ancestor interface Element when it has no arguments. + ChildNode::remove_binding(); +} + +void HTMLSelectElement::remove(WebIDL::Long index) +{ + const_cast(*options()).remove(index); +} + // https://html.spec.whatwg.org/multipage/form-elements.html#concept-select-option-list Vector> HTMLSelectElement::list_of_options() const { diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h index f815f4b906e..95ffe5ad7f7 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h @@ -39,6 +39,8 @@ public: DOM::Element* item(size_t index); DOM::Element* named_item(FlyString const& name); WebIDL::ExceptionOr add(HTMLOptionOrOptGroupElement element, Optional before = {}); + void remove(); + void remove(WebIDL::Long); int selected_index() const; void set_selected_index(int); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.idl b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.idl index 1638cef9a9e..52bbb71192f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.idl +++ b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.idl @@ -24,8 +24,8 @@ interface HTMLSelectElement : HTMLElement { // FIXME: Element is really HTMLOptionElement Element? namedItem(DOMString name); [CEReactions] undefined add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null); - // FIXME: [CEReactions] undefined remove(); // ChildNode overload - // FIXME: [CEReactions] undefined remove(long index); + [CEReactions] undefined remove(); // ChildNode overload + [CEReactions] undefined remove(long index); // FIXME: [CEReactions] setter undefined (unsigned long index, HTMLOptionElement? option); // FIXME: [SameObject] readonly attribute HTMLCollection selectedOptions;