2024-12-12 19:53:04 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Copyright  ( c )  2024 ,  Tim  Ledbetter  < tim . ledbetter @ ladybird . org > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  SPDX - License - Identifier :  BSD - 2 - Clause 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 15:15:38 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibWeb/DOM/Document.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-12 19:53:04 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibWeb/DOM/Element.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 15:15:38 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibWeb/DOM/Node.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-12 19:53:04 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibWeb/HTML/AttributeNames.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 15:15:38 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibWeb/HTML/FormAssociatedElement.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibWeb/HTML/HTMLElement.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-12 19:53:04 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibWeb/HTML/PopoverInvokerElement.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								namespace  Web : : HTML  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  PopoverInvokerElement : : associated_attribute_changed ( FlyString  const &  name ,  Optional < String >  const & ,  Optional < FlyString >  const &  namespace_ ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // From: https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributess
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // For element reflected targets only: the following attribute change steps, given element, localName, oldValue, value, and namespace,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // are used to synchronize between the content attribute and the IDL attribute:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 1. If localName is not attr or namespace is not null, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( name  ! =  HTML : : AttributeNames : : popovertarget  | |  namespace_ . has_value ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 2. Set element's explicitly set attr-elements to null.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    m_popover_target_element  =  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  PopoverInvokerElement : : visit_edges ( JS : : Cell : : Visitor &  visitor ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    visitor . visit ( m_popover_target_element ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 15:15:38 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// https://html.spec.whatwg.org/multipage/popover.html#popover-target-attribute-activation-behavior
 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 11:06:06 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// https://whatpr.org/html/9457/popover.html#popover-target-attribute-activation-behavior
 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 15:15:38 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								void  PopoverInvokerElement : : popover_target_activation_behaviour ( GC : : Ref < DOM : : Node >  node ,  GC : : Ref < DOM : : Node >  event_target ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // To run the popover target attribute activation behavior given a Node node and a Node eventTarget:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 1. Let popover be node's popover target element.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  popover  =  PopoverInvokerElement : : get_the_popover_target_element ( node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 2. If popover is null, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! popover ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 3. If eventTarget is a shadow-including inclusive descendant of popover and popover is a shadow-including descendant of node, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( event_target - > is_shadow_including_inclusive_descendant_of ( * popover ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        & &  popover - > is_shadow_including_descendant_of ( node ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 4. If node's popovertargetaction attribute is in the show state and popover's popover visibility state is showing, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( as < DOM : : Element > ( * node ) . get_attribute_value ( HTML : : AttributeNames : : popovertargetaction ) . equals_ignoring_ascii_case ( " show " sv ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        & &  popover - > popover_visibility_state ( )  = =  HTMLElement : : PopoverVisibilityState : : Showing ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 5. If node's popovertargetaction attribute is in the hide state and popover's popover visibility state is hidden, then return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( as < DOM : : Element > ( * node ) . get_attribute_value ( HTML : : AttributeNames : : popovertargetaction ) . equals_ignoring_ascii_case ( " hide " sv ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        & &  popover - > popover_visibility_state ( )  = =  HTMLElement : : PopoverVisibilityState : : Hidden ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-06-04 15:35:43 +10:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // 6. If popover's popover visibility state is showing, then run the hide popover algorithm given popover, true, true, false, false, and node.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 15:15:38 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( popover - > popover_visibility_state ( )  = =  HTMLElement : : PopoverVisibilityState : : Showing )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-04 15:35:43 +10:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        MUST ( popover - > hide_popover ( FocusPreviousElement : : Yes ,  FireEvents : : Yes ,  ThrowExceptions : : No ,  IgnoreDomState : : No ,  as < HTMLElement > ( * node ) ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 15:15:38 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 11:06:06 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // 7. Otherwise, if popover's popover visibility state is hidden and the result of running check popover validity given popover, false, false, null, and false is true, then run show popover given popover, false, and node.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 15:15:38 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    else  if  ( popover - > popover_visibility_state ( )  = =  HTMLElement : : PopoverVisibilityState : : Hidden 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 11:06:06 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        & &  MUST ( popover - > check_popover_validity ( ExpectedToBeShowing : : No ,  ThrowExceptions : : No ,  nullptr ,  IgnoreDomState : : No ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 15:15:38 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        MUST ( popover - > show_popover ( ThrowExceptions : : No ,  as < HTMLElement > ( * node ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								// https://html.spec.whatwg.org/multipage/popover.html#popover-target-element
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								GC : : Ptr < HTMLElement >  PopoverInvokerElement : : get_the_popover_target_element ( GC : : Ref < DOM : : Node >  node ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // To get the popover target element given a Node node, perform the following steps. They return an HTML element or null.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-13 18:58:40 +10:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  const *  form_associated_element  =  as_if < FormAssociatedElement > ( * node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! form_associated_element ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 15:15:38 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 1. If node is not a button, then return null.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! form_associated_element - > is_button ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 2. If node is disabled, then return null.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! form_associated_element - > enabled ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 3. If node has a form owner and node is a submit button, then return null.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( form_associated_element - > form ( )  ! =  nullptr  & &  form_associated_element - > is_submit_button ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 4. Let popoverElement be the result of running node's get the popovertarget-associated element.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 11:59:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  const *  popover_invoker_element  =  as_if < PopoverInvokerElement > ( * node ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 15:15:38 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    GC : : Ptr < HTMLElement >  popover_element  =  as < HTMLElement > ( popover_invoker_element - > m_popover_target_element . ptr ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! popover_element )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  target_id  =  as < HTMLElement > ( * node ) . attribute ( " popovertarget " _fly_string ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( target_id . has_value ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            node - > root ( ) . for_each_in_inclusive_subtree_of_type < HTMLElement > ( [ & ] ( auto &  candidate )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( candidate . attribute ( HTML : : AttributeNames : : id )  = =  target_id . value ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    popover_element  =  & candidate ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    return  TraversalDecision : : Break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  TraversalDecision : : Continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 5. If popoverElement is null, then return null.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! popover_element ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-07-08 10:21:00 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // 6. If popoverElement's popover attribute is in the No Popover state, then return null.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-14 15:15:38 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ! popover_element - > popover ( ) . has_value ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 7. Return popoverElement.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  popover_element ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-12 19:53:04 +00:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								}