diff options
author | Timothy Flynn <trflynn89@pm.me> | 2022-03-21 20:02:40 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-03-22 02:08:15 +0100 |
commit | ff9856a21447445394ce34543b301ac9a9460d57 (patch) | |
tree | 172df9841bb7da583f05eacd93e3c2924285d30b | |
parent | 5133491714d74105476291697c238618ced5003e (diff) | |
download | serenity-ff9856a21447445394ce34543b301ac9a9460d57.zip |
LibWeb: Implement HTMLOptionsCollection.add()
3 files changed, 51 insertions, 1 deletions
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp index 7e5484506a..365f75ed3b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp @@ -4,7 +4,11 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/DOM/DOMException.h> +#include <LibWeb/HTML/HTMLOptGroupElement.h> +#include <LibWeb/HTML/HTMLOptionElement.h> #include <LibWeb/HTML/HTMLOptionsCollection.h> +#include <LibWeb/HTML/HTMLSelectElement.h> namespace Web::HTML { @@ -13,4 +17,43 @@ HTMLOptionsCollection::HTMLOptionsCollection(DOM::ParentNode& root, Function<boo { } +// https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#dom-htmloptionscollection-add +DOM::ExceptionOr<void> HTMLOptionsCollection::add(HTMLOptionOrOptGroupElement element, Optional<HTMLElementOrElementIndex> before) +{ + auto resolved_element = element.visit([](auto const& e) -> NonnullRefPtr<HTMLElement> { return e; }); + + RefPtr<DOM::Node> before_element; + if (before.has_value() && before->has<NonnullRefPtr<HTMLElement>>()) + before_element = before->get<NonnullRefPtr<HTMLElement>>(); + + // 1. If element is an ancestor of the select element on which the HTMLOptionsCollection is rooted, then throw a "HierarchyRequestError" DOMException. + if (resolved_element->is_ancestor_of(root())) + return DOM::HierarchyRequestError::create("The provided element is an ancestor of the root select element."); + + // 2. If before is an element, but that element isn't a descendant of the select element on which the HTMLOptionsCollection is rooted, then throw a "NotFoundError" DOMException. + if (before_element && !before_element->is_descendant_of(root())) + return DOM::NotFoundError::create("The 'before' element is not a descendant of the root select element."); + + // 3. If element and before are the same element, then return. + if (before_element && (resolved_element.ptr() == before_element.ptr())) + return {}; + + // 4. If before is a node, then let reference be that node. Otherwise, if before is an integer, and there is a beforeth node in the collection, let reference be that node. Otherwise, let reference be null. + RefPtr<DOM::Node> reference; + + if (before_element) + reference = move(before_element); + else if (before.has_value() && before->has<i32>()) + reference = item(before->get<i32>()); + + // 5. If reference is not null, let parent be the parent node of reference. Otherwise, let parent be the select element on which the HTMLOptionsCollection is rooted. + DOM::Node* parent = reference ? reference->parent() : root().ptr(); + + // 6. Pre-insert element into parent node before reference. + if (auto result = parent->pre_insert(resolved_element, reference); result.is_exception()) + return result.exception(); + + return {}; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.h b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.h index 1d2bfcd2c5..7444607cfd 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.h @@ -6,10 +6,15 @@ #pragma once +#include <AK/Variant.h> +#include <LibWeb/DOM/ExceptionOr.h> #include <LibWeb/DOM/HTMLCollection.h> namespace Web::HTML { +using HTMLOptionOrOptGroupElement = Variant<NonnullRefPtr<HTMLOptionElement>, NonnullRefPtr<HTMLOptGroupElement>>; +using HTMLElementOrElementIndex = Variant<NonnullRefPtr<HTMLElement>, i32>; + class HTMLOptionsCollection final : public DOM::HTMLCollection { public: using WrapperType = Bindings::HTMLOptionsCollectionWrapper; @@ -19,6 +24,8 @@ public: return adopt_ref(*new HTMLOptionsCollection(root, move(filter))); } + DOM::ExceptionOr<void> add(HTMLOptionOrOptGroupElement element, Optional<HTMLElementOrElementIndex> before = {}); + protected: HTMLOptionsCollection(DOM::ParentNode& root, Function<bool(DOM::Element const&)> filter); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.idl b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.idl index ae33079903..084317ab03 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.idl +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.idl @@ -6,7 +6,7 @@ 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 add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null); // [CEReactions] undefined remove(long index); // attribute long selectedIndex; }; |