summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2022-03-21 20:02:40 -0400
committerAndreas Kling <kling@serenityos.org>2022-03-22 02:08:15 +0100
commitff9856a21447445394ce34543b301ac9a9460d57 (patch)
tree172df9841bb7da583f05eacd93e3c2924285d30b
parent5133491714d74105476291697c238618ced5003e (diff)
downloadserenity-ff9856a21447445394ce34543b301ac9a9460d57.zip
LibWeb: Implement HTMLOptionsCollection.add()
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.cpp43
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.h7
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLOptionsCollection.idl2
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;
};