2020-06-07 23:10:45 +02:00
/*
2022-02-26 11:43:52 +01:00
* Copyright ( c ) 2020 - 2022 , Andreas Kling < kling @ serenityos . org >
2020-06-07 23:10:45 +02:00
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-06-07 23:10:45 +02:00
*/
2024-04-27 12:09:58 +12:00
# include <LibWeb/Bindings/HTMLTableRowElementPrototype.h>
2022-09-30 17:16:16 -06:00
# include <LibWeb/Bindings/Intrinsics.h>
2023-11-19 16:20:29 +04:00
# include <LibWeb/CSS/Parser/Parser.h>
# include <LibWeb/CSS/Parser/ParsingContext.h>
2023-07-04 17:18:59 +02:00
# include <LibWeb/CSS/StyleProperties.h>
# include <LibWeb/CSS/StyleValues/ColorStyleValue.h>
2023-11-19 16:20:29 +04:00
# include <LibWeb/CSS/StyleValues/IdentifierStyleValue.h>
2023-07-07 11:42:25 +02:00
# include <LibWeb/CSS/StyleValues/ImageStyleValue.h>
# include <LibWeb/DOM/Document.h>
2022-11-05 15:18:50 +00:00
# include <LibWeb/DOM/ElementFactory.h>
2022-02-26 11:43:52 +01:00
# include <LibWeb/DOM/HTMLCollection.h>
# include <LibWeb/HTML/HTMLTableCellElement.h>
2022-03-21 16:15:10 +01:00
# include <LibWeb/HTML/HTMLTableElement.h>
2020-07-26 15:08:16 +02:00
# include <LibWeb/HTML/HTMLTableRowElement.h>
2022-03-21 16:15:10 +01:00
# include <LibWeb/HTML/HTMLTableSectionElement.h>
2023-07-04 17:18:59 +02:00
# include <LibWeb/HTML/Parser/HTMLParser.h>
2022-11-05 15:18:50 +00:00
# include <LibWeb/Namespace.h>
2020-06-07 23:10:45 +02:00
2020-07-28 18:20:36 +02:00
namespace Web : : HTML {
2020-06-07 23:10:45 +02:00
2023-11-19 19:47:52 +01:00
JS_DEFINE_ALLOCATOR ( HTMLTableRowElement ) ;
2022-02-18 21:00:52 +01:00
HTMLTableRowElement : : HTMLTableRowElement ( DOM : : Document & document , DOM : : QualifiedName qualified_name )
2021-02-07 11:20:15 +01:00
: HTMLElement ( document , move ( qualified_name ) )
2020-06-07 23:10:45 +02:00
{
}
2022-03-14 13:21:51 -06:00
HTMLTableRowElement : : ~ HTMLTableRowElement ( ) = default ;
2020-06-07 23:10:45 +02:00
2023-08-07 08:41:28 +02:00
void HTMLTableRowElement : : initialize ( JS : : Realm & realm )
2023-01-10 06:28:20 -05:00
{
2023-08-07 08:41:28 +02:00
Base : : initialize ( realm ) ;
2024-03-16 13:13:08 +01:00
WEB_SET_PROTOTYPE_FOR_INTERFACE ( HTMLTableRowElement ) ;
2023-01-10 06:28:20 -05:00
}
2023-07-04 17:18:59 +02:00
void HTMLTableRowElement : : apply_presentational_hints ( CSS : : StyleProperties & style ) const
{
Base : : apply_presentational_hints ( style ) ;
for_each_attribute ( [ & ] ( auto & name , auto & value ) {
if ( name = = HTML : : AttributeNames : : bgcolor ) {
// https://html.spec.whatwg.org/multipage/rendering.html#tables-2:rules-for-parsing-a-legacy-colour-value
auto color = parse_legacy_color_value ( value ) ;
if ( color . has_value ( ) )
2023-08-19 14:00:10 +01:00
style . set_property ( CSS : : PropertyID : : BackgroundColor , CSS : : ColorStyleValue : : create ( color . value ( ) ) ) ;
2023-07-04 17:18:59 +02:00
return ;
2023-07-07 11:42:25 +02:00
} else if ( name = = HTML : : AttributeNames : : background ) {
if ( auto parsed_value = document ( ) . parse_url ( value ) ; parsed_value . is_valid ( ) )
2023-08-19 14:00:10 +01:00
style . set_property ( CSS : : PropertyID : : BackgroundImage , CSS : : ImageStyleValue : : create ( parsed_value ) ) ;
2023-07-07 11:42:25 +02:00
return ;
2023-11-19 16:20:29 +04:00
} else if ( name = = HTML : : AttributeNames : : valign ) {
2024-01-16 19:04:45 +01:00
if ( auto parsed_value = parse_css_value ( CSS : : Parser : : ParsingContext { document ( ) } , value , CSS : : PropertyID : : VerticalAlign ) )
2023-11-19 16:20:29 +04:00
style . set_property ( CSS : : PropertyID : : VerticalAlign , parsed_value . release_nonnull ( ) ) ;
return ;
2023-07-04 17:18:59 +02:00
}
} ) ;
}
2022-11-24 19:03:22 +01:00
void HTMLTableRowElement : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
visitor . visit ( m_cells ) ;
}
2022-02-26 11:43:52 +01:00
// https://html.spec.whatwg.org/multipage/tables.html#dom-tr-cells
2022-09-01 20:50:16 +02:00
JS : : NonnullGCPtr < DOM : : HTMLCollection > HTMLTableRowElement : : cells ( ) const
2022-02-26 11:43:52 +01:00
{
// The cells attribute must return an HTMLCollection rooted at this tr element,
// whose filter matches only td and th elements that are children of the tr element.
2022-11-24 19:03:22 +01:00
if ( ! m_cells ) {
2023-05-23 11:25:07 +02:00
m_cells = DOM : : HTMLCollection : : create ( const_cast < HTMLTableRowElement & > ( * this ) , DOM : : HTMLCollection : : Scope : : Children , [ ] ( Element const & element ) {
return is < HTMLTableCellElement > ( element ) ;
2023-08-13 13:05:26 +02:00
} ) ;
2022-11-24 19:03:22 +01:00
}
return * m_cells ;
2022-02-26 11:43:52 +01:00
}
2022-03-21 16:15:10 +01:00
// https://html.spec.whatwg.org/multipage/tables.html#dom-tr-rowindex
int HTMLTableRowElement : : row_index ( ) const
{
// The rowIndex attribute must, if this element has a parent table element,
// or a parent tbody, thead, or tfoot element and a grandparent table element,
// return the index of this tr element in that table element's rows collection.
// If there is no such table element, then the attribute must return − 1.
2022-09-01 20:50:16 +02:00
auto rows_collection = [ & ] ( ) - > JS : : GCPtr < DOM : : HTMLCollection > {
2022-03-21 16:15:10 +01:00
if ( ! parent ( ) )
return nullptr ;
if ( is < HTMLTableElement > ( * parent ( ) ) )
return const_cast < HTMLTableElement & > ( static_cast < HTMLTableElement const & > ( * parent ( ) ) ) . rows ( ) ;
if ( is < HTMLTableSectionElement > ( * parent ( ) ) & & parent ( ) - > parent ( ) & & is < HTMLTableElement > ( * parent ( ) - > parent ( ) ) )
return const_cast < HTMLTableElement & > ( static_cast < HTMLTableElement const & > ( * parent ( ) - > parent ( ) ) ) . rows ( ) ;
return nullptr ;
} ( ) ;
if ( ! rows_collection )
return - 1 ;
auto rows = rows_collection - > collect_matching_elements ( ) ;
for ( size_t i = 0 ; i < rows . size ( ) ; + + i ) {
2022-08-28 13:42:07 +02:00
if ( rows [ i ] = = this )
2022-03-21 16:15:10 +01:00
return i ;
}
return - 1 ;
}
int HTMLTableRowElement : : section_row_index ( ) const
{
// The sectionRowIndex attribute must, if this element has a parent table, tbody, thead, or tfoot element,
// return the index of the tr element in the parent element's rows collection
// (for tables, that's HTMLTableElement's rows collection; for table sections, that's HTMLTableSectionElement's rows collection).
// If there is no such parent element, then the attribute must return − 1.
2022-09-01 20:50:16 +02:00
auto rows_collection = [ & ] ( ) - > JS : : GCPtr < DOM : : HTMLCollection > {
2022-03-21 16:15:10 +01:00
if ( ! parent ( ) )
return nullptr ;
if ( is < HTMLTableElement > ( * parent ( ) ) )
return const_cast < HTMLTableElement & > ( static_cast < HTMLTableElement const & > ( * parent ( ) ) ) . rows ( ) ;
if ( is < HTMLTableSectionElement > ( * parent ( ) ) )
return static_cast < HTMLTableSectionElement const & > ( * parent ( ) ) . rows ( ) ;
return nullptr ;
} ( ) ;
if ( ! rows_collection )
return - 1 ;
auto rows = rows_collection - > collect_matching_elements ( ) ;
for ( size_t i = 0 ; i < rows . size ( ) ; + + i ) {
2022-08-28 13:42:07 +02:00
if ( rows [ i ] = = this )
2022-03-21 16:15:10 +01:00
return i ;
}
return - 1 ;
}
2022-11-05 15:18:50 +00:00
// https://html.spec.whatwg.org/multipage/tables.html#dom-tr-insertcell
WebIDL : : ExceptionOr < JS : : NonnullGCPtr < HTMLTableCellElement > > HTMLTableRowElement : : insert_cell ( i32 index )
{
auto cells_collection = cells ( ) ;
auto cells_collection_size = static_cast < i32 > ( cells_collection - > length ( ) ) ;
// 1. If index is less than − 1 or greater than the number of elements in the cells collection, then throw an "IndexSizeError" DOMException.
if ( index < - 1 | | index > cells_collection_size )
2023-09-06 16:03:01 +12:00
return WebIDL : : IndexSizeError : : create ( realm ( ) , " Index is negative or greater than the number of cells " _fly_string ) ;
2022-11-05 15:18:50 +00:00
// 2. Let table cell be the result of creating an element given this tr element's node document, td, and the HTML namespace.
2023-11-04 18:42:04 +01:00
auto & table_cell = static_cast < HTMLTableCellElement & > ( * TRY ( DOM : : create_element ( document ( ) , HTML : : TagNames : : td , Namespace : : HTML ) ) ) ;
2022-11-05 15:18:50 +00:00
// 3. If index is equal to − 1 or equal to the number of items in cells collection, then append table cell to this tr element.
if ( index = = - 1 | | index = = cells_collection_size )
TRY ( append_child ( table_cell ) ) ;
// 4. Otherwise, insert table cell as a child of this tr element, immediately before the indexth td or th element in the cells collection.
else
insert_before ( table_cell , cells_collection - > item ( index ) ) ;
// 5. Return table cell.
return JS : : NonnullGCPtr ( table_cell ) ;
}
2022-11-05 15:19:16 +00:00
// https://html.spec.whatwg.org/multipage/tables.html#dom-tr-deletecell
WebIDL : : ExceptionOr < void > HTMLTableRowElement : : delete_cell ( i32 index )
{
auto cells_collection = cells ( ) ;
auto cells_collection_size = static_cast < i32 > ( cells_collection - > length ( ) ) ;
// 1. If index is less than − 1 or greater than or equal to the number of elements in the cells collection, then throw an "IndexSizeError" DOMException.
if ( index < - 1 | | index > = cells_collection_size )
2023-09-06 16:03:01 +12:00
return WebIDL : : IndexSizeError : : create ( realm ( ) , " Index is negative or greater than or equal to the number of cells " _fly_string ) ;
2022-11-05 15:19:16 +00:00
// 2. If index is − 1, then remove the last element in the cells collection from its parent, or do nothing if the cells collection is empty.
if ( index = = - 1 ) {
if ( cells_collection_size > 0 )
cells_collection - > item ( cells_collection_size - 1 ) - > remove ( ) ;
}
// 3. Otherwise, remove the indexth element in the cells collection from its parent.
else {
cells_collection - > item ( index ) - > remove ( ) ;
}
return { } ;
}
2020-06-07 23:10:45 +02:00
}