2023-08-20 14:41:51 +12:00
/*
* Copyright ( c ) 2023 , Shannon Booth < shannon @ serenityos . org >
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2024-04-27 12:09:58 +12:00
# include <LibWeb/Bindings/HTMLFormControlsCollectionPrototype.h>
2023-08-20 14:41:51 +12:00
# include <LibWeb/Bindings/Intrinsics.h>
# include <LibWeb/DOM/Element.h>
# include <LibWeb/DOM/HTMLCollection.h>
# include <LibWeb/DOM/ParentNode.h>
2024-11-02 09:22:13 -04:00
# include <LibWeb/HTML/HTMLFormControlsCollection.h>
# include <LibWeb/HTML/RadioNodeList.h>
2023-08-20 14:41:51 +12:00
2024-11-02 09:22:13 -04:00
namespace Web : : HTML {
2023-08-20 14:41:51 +12:00
2024-11-15 04:01:23 +13:00
GC_DEFINE_ALLOCATOR ( HTMLFormControlsCollection ) ;
2023-11-19 19:47:52 +01:00
2024-11-15 04:01:23 +13:00
GC : : Ref < HTMLFormControlsCollection > HTMLFormControlsCollection : : create ( DOM : : ParentNode & root , Scope scope , Function < bool ( DOM : : Element const & ) > filter )
2023-08-20 14:41:51 +12:00
{
2024-11-14 05:50:17 +13:00
return root . realm ( ) . create < HTMLFormControlsCollection > ( root , scope , move ( filter ) ) ;
2023-08-20 14:41:51 +12:00
}
2024-11-02 09:22:13 -04:00
HTMLFormControlsCollection : : HTMLFormControlsCollection ( DOM : : ParentNode & root , Scope scope , Function < bool ( DOM : : Element const & ) > filter )
: DOM : : HTMLCollection ( root , scope , move ( filter ) )
2023-08-20 14:41:51 +12:00
{
}
HTMLFormControlsCollection : : ~ HTMLFormControlsCollection ( ) = default ;
void HTMLFormControlsCollection : : initialize ( JS : : Realm & realm )
{
Base : : initialize ( realm ) ;
2024-03-16 13:13:08 +01:00
WEB_SET_PROTOTYPE_FOR_INTERFACE ( HTMLFormControlsCollection ) ;
2023-08-20 14:41:51 +12:00
}
// https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#dom-htmlformcontrolscollection-nameditem
2024-11-15 04:01:23 +13:00
Variant < Empty , DOM : : Element * , GC : : Root < RadioNodeList > > HTMLFormControlsCollection : : named_item_or_radio_node_list ( FlyString const & name ) const
2023-08-20 14:41:51 +12:00
{
// 1. If name is the empty string, return null and stop the algorithm.
if ( name . is_empty ( ) )
return { } ;
// 2. If, at the time the method is called, there is exactly one node in the collection that has either an id attribute or a name attribute equal to name, then return that node and stop the algorithm.
// 3. Otherwise, if there are no nodes in the collection that have either an id attribute or a name attribute equal to name, then return null and stop the algorithm.
2024-11-02 09:22:13 -04:00
DOM : : Element * matching_element = nullptr ;
2023-08-20 14:41:51 +12:00
bool multiple_matching = false ;
auto collection = collect_matching_elements ( ) ;
for ( auto const & element : collection ) {
2024-01-13 20:12:23 +13:00
if ( element - > id ( ) ! = name & & element - > name ( ) ! = name )
2023-08-20 14:41:51 +12:00
continue ;
if ( matching_element ) {
multiple_matching = true ;
break ;
}
matching_element = element ;
}
if ( ! matching_element )
return { } ;
if ( ! multiple_matching )
return matching_element ;
// 4. Otherwise, create a new RadioNodeList object representing a live view of the HTMLFormControlsCollection object, further filtered so that the only nodes in the
// RadioNodeList object are those that have either an id attribute or a name attribute equal to name. The nodes in the RadioNodeList object must be sorted in tree
// order. Return that RadioNodeList object.
2024-11-15 04:01:23 +13:00
return GC : : make_root ( RadioNodeList : : create ( realm ( ) , root ( ) , DOM : : LiveNodeList : : Scope : : Descendants , [ name ] ( auto const & node ) {
2024-11-02 09:22:13 -04:00
if ( ! is < DOM : : Element > ( node ) )
2023-08-20 14:41:51 +12:00
return false ;
2024-11-02 09:22:13 -04:00
auto const & element = verify_cast < DOM : : Element > ( node ) ;
2024-01-13 20:12:23 +13:00
return element . id ( ) = = name | | element . name ( ) = = name ;
2023-08-20 14:41:51 +12:00
} ) ) ;
}
2024-07-25 17:36:10 +12:00
JS : : Value HTMLFormControlsCollection : : named_item_value ( FlyString const & name ) const
2023-12-21 22:04:26 +13:00
{
return named_item_or_radio_node_list ( name ) . visit (
[ ] ( Empty ) - > JS : : Value { return JS : : js_undefined ( ) ; } ,
[ ] ( auto const & value ) - > JS : : Value { return value ; } ) ;
}
2023-08-20 14:41:51 +12:00
}