2022-03-16 12:58:28 +01:00
/*
* Copyright ( c ) 2022 , the SerenityOS developers .
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2022-03-21 20:02:40 -04:00
# include <LibWeb/DOM/DOMException.h>
# include <LibWeb/HTML/HTMLOptGroupElement.h>
# include <LibWeb/HTML/HTMLOptionElement.h>
2022-03-16 12:58:28 +01:00
# include <LibWeb/HTML/HTMLOptionsCollection.h>
2022-03-21 20:02:40 -04:00
# include <LibWeb/HTML/HTMLSelectElement.h>
2022-09-01 20:50:16 +02:00
# include <LibWeb/HTML/Window.h>
2022-03-16 12:58:28 +01:00
namespace Web : : HTML {
2022-09-01 20:50:16 +02:00
JS : : NonnullGCPtr < HTMLOptionsCollection > HTMLOptionsCollection : : create ( DOM : : ParentNode & root , Function < bool ( DOM : : Element const & ) > filter )
{
return * root . heap ( ) . allocate < HTMLOptionsCollection > ( root . realm ( ) , root , move ( filter ) ) ;
}
2022-03-16 12:58:28 +01:00
HTMLOptionsCollection : : HTMLOptionsCollection ( DOM : : ParentNode & root , Function < bool ( DOM : : Element const & ) > filter )
: DOM : : HTMLCollection ( root , move ( filter ) )
{
2022-09-03 18:43:24 +02:00
set_prototype ( & root . window ( ) . cached_web_prototype ( " HTMLOptionsCollection " ) ) ;
2022-03-16 12:58:28 +01:00
}
2022-09-01 20:50:16 +02:00
HTMLOptionsCollection : : ~ HTMLOptionsCollection ( ) = default ;
2022-03-21 20:02:40 -04:00
// https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#dom-htmloptionscollection-add
DOM : : ExceptionOr < void > HTMLOptionsCollection : : add ( HTMLOptionOrOptGroupElement element , Optional < HTMLElementOrElementIndex > before )
{
2022-08-28 13:42:07 +02:00
auto resolved_element = element . visit (
[ ] ( auto & e ) - > JS : : Handle < HTMLElement > {
return JS : : make_handle ( static_cast < HTML : : HTMLElement & > ( * e ) ) ;
} ) ;
2022-03-21 20:02:40 -04:00
2022-08-28 13:42:07 +02:00
JS : : GCPtr < DOM : : Node > before_element ;
if ( before . has_value ( ) & & before - > has < JS : : Handle < HTMLElement > > ( ) )
before_element = before - > get < JS : : Handle < HTMLElement > > ( ) . ptr ( ) ;
2022-03-21 20:02:40 -04:00
// 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 ( ) ) )
2022-09-04 16:56:15 +02:00
return DOM : : HierarchyRequestError : : create ( global_object ( ) , " The provided element is an ancestor of the root select element. " ) ;
2022-03-21 20:02:40 -04:00
// 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 ( ) ) )
2022-09-04 16:56:15 +02:00
return DOM : : NotFoundError : : create ( global_object ( ) , " The 'before' element is not a descendant of the root select element. " ) ;
2022-03-21 20:02:40 -04:00
// 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.
2022-08-28 13:42:07 +02:00
JS : : GCPtr < DOM : : Node > reference ;
2022-03-21 20:02:40 -04:00
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.
2022-08-28 13:42:07 +02:00
( void ) TRY ( parent - > pre_insert ( * resolved_element , reference ) ) ;
2022-03-21 20:02:40 -04:00
return { } ;
}
2022-03-16 12:58:28 +01:00
}