2020-07-31 23:04:26 -03:00
/*
2021-04-28 17:46:44 -03:00
* Copyright ( c ) 2020 , the SerenityOS developers .
2020-07-31 23:04:26 -03:00
*
2021-04-22 05:24:48 -03:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-07-31 23:04:26 -03:00
*/
2024-04-26 21:09:58 -03:00
# include <LibWeb/Bindings/HTMLButtonElementPrototype.h>
2022-03-01 18:12:32 -03:00
# include <LibWeb/DOM/Document.h>
2025-01-14 01:15:38 -03:00
# include <LibWeb/DOM/Event.h>
2020-07-31 23:04:26 -03:00
# include <LibWeb/HTML/HTMLButtonElement.h>
2022-03-01 18:12:32 -03:00
# include <LibWeb/HTML/HTMLFormElement.h>
2020-07-31 23:04:26 -03:00
namespace Web : : HTML {
2024-11-14 12:01:23 -03:00
GC_DEFINE_ALLOCATOR ( HTMLButtonElement ) ;
2023-11-19 15:47:52 -03:00
2022-02-18 17:00:52 -03:00
HTMLButtonElement : : HTMLButtonElement ( DOM : : Document & document , DOM : : QualifiedName qualified_name )
2022-03-23 19:55:54 -03:00
: HTMLElement ( document , move ( qualified_name ) )
2020-07-31 23:04:26 -03:00
{
}
2022-03-14 16:21:51 -03:00
HTMLButtonElement : : ~ HTMLButtonElement ( ) = default ;
2020-07-31 23:04:26 -03:00
2023-08-07 03:41:28 -03:00
void HTMLButtonElement : : initialize ( JS : : Realm & realm )
2023-01-10 08:28:20 -03:00
{
2023-08-07 03:41:28 -03:00
Base : : initialize ( realm ) ;
2024-03-16 09:13:08 -03:00
WEB_SET_PROTOTYPE_FOR_INTERFACE ( HTMLButtonElement ) ;
2023-01-10 08:28:20 -03:00
}
2022-03-01 18:06:29 -03:00
HTMLButtonElement : : TypeAttributeState HTMLButtonElement : : type_state ( ) const
{
2024-01-16 15:04:45 -03:00
auto value = get_attribute_value ( HTML : : AttributeNames : : type ) ;
2022-03-01 18:06:29 -03:00
# define __ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTE(keyword, state) \
2023-03-10 04:48:54 -03:00
if ( value . equals_ignoring_ascii_case ( # keyword # # sv ) ) \
2022-03-01 18:06:29 -03:00
return HTMLButtonElement : : TypeAttributeState : : state ;
ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTES
# undef __ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTE
2025-02-20 14:01:28 -03:00
// The attribute's missing value default and invalid value default are both the Auto state.
// https://html.spec.whatwg.org/multipage/form-elements.html#attr-button-type-auto-state
return HTMLButtonElement : : TypeAttributeState : : Auto ;
2022-03-01 18:06:29 -03:00
}
2025-02-20 14:01:28 -03:00
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-button-type
String HTMLButtonElement : : type_for_bindings ( ) const
2022-03-01 18:06:29 -03:00
{
2025-02-20 14:01:28 -03:00
// The type getter steps are:
// 1. If this is a submit button, then return "submit".
if ( is_submit_button ( ) )
return " submit " _string ;
// 2. Let state be this's type attribute.
auto state = type_state ( ) ;
// 3. Assert: state is not in the Submit Button state.
VERIFY ( state ! = TypeAttributeState : : Submit ) ;
// 4. If state is in the Auto state, then return "button".
if ( state = = TypeAttributeState : : Auto )
return " button " _string ;
// 5. Return the keyword value corresponding to state.
switch ( state ) {
# define __ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTE(keyword, state) \
case TypeAttributeState : : state : \
return # keyword # # _string ;
ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTES
# undef __ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTE
}
VERIFY_NOT_REACHED ( ) ;
}
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-button-type
WebIDL : : ExceptionOr < void > HTMLButtonElement : : set_type_for_bindings ( String const & type )
{
// The type setter steps are to set the type content attribute to the given value.
2023-05-25 16:37:57 -03:00
return set_attribute ( HTML : : AttributeNames : : type , type ) ;
2022-03-01 18:06:29 -03:00
}
2024-12-12 16:53:04 -03:00
void HTMLButtonElement : : form_associated_element_attribute_changed ( FlyString const & name , Optional < String > const & value , Optional < FlyString > const & namespace_ )
{
PopoverInvokerElement : : associated_attribute_changed ( name , value , namespace_ ) ;
}
2024-11-23 19:06:06 -03:00
void HTMLButtonElement : : visit_edges ( Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
PopoverInvokerElement : : visit_edges ( visitor ) ;
2025-04-03 20:27:55 -03:00
visitor . visit ( m_command_for_element ) ;
2024-11-23 19:06:06 -03:00
}
2022-11-05 00:58:14 -03:00
// https://html.spec.whatwg.org/multipage/interaction.html#dom-tabindex
i32 HTMLButtonElement : : default_tab_index_value ( ) const
{
// See the base function for the spec comments.
return 0 ;
}
2023-06-18 11:08:15 -03:00
// https://html.spec.whatwg.org/multipage/forms.html#concept-submit-button
// https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:concept-submit-button
bool HTMLButtonElement : : is_submit_button ( ) const
{
2025-02-20 14:01:28 -03:00
// A button element is said to be a submit button if any of the following are true:
switch ( type_state ( ) ) {
// - the type attribute is in the Auto state and both the command and commandfor content attributes are not present; or
case TypeAttributeState : : Auto :
return ! has_attribute ( AttributeNames : : command ) & & ! has_attribute ( AttributeNames : : commandfor ) ;
// - the type attribute is in the Submit Button state.
case TypeAttributeState : : Submit :
return true ;
default :
return false ;
}
2023-06-18 11:08:15 -03:00
}
// https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:concept-fe-value
2023-11-20 04:32:40 -03:00
String HTMLButtonElement : : value ( ) const
2023-06-18 11:08:15 -03:00
{
2023-11-20 04:32:40 -03:00
return attribute ( AttributeNames : : value ) . value_or ( String { } ) ;
2023-06-18 11:08:15 -03:00
}
2023-11-18 06:48:09 -03:00
bool HTMLButtonElement : : has_activation_behavior ( ) const
{
return true ;
}
2024-01-18 16:58:22 -03:00
void HTMLButtonElement : : activation_behavior ( DOM : : Event const & event )
2023-11-18 06:48:09 -03:00
{
// https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:activation-behaviour
// 1. If element is disabled, then return.
if ( ! enabled ( ) )
return ;
2024-01-18 16:58:22 -03:00
// 2. If element's node document is not fully active, then return.
2023-11-18 06:48:09 -03:00
if ( ! this - > document ( ) . is_fully_active ( ) )
return ;
2025-02-12 13:58:03 -03:00
// 3. If element has a form owner:
2024-01-18 16:58:22 -03:00
if ( form ( ) ! = nullptr ) {
2025-02-26 20:53:48 -03:00
// 1. If element is a submit button, then submit element's form owner from element with userInvolvement set to event's user navigation involvement, and return.
2025-02-12 13:58:03 -03:00
if ( is_submit_button ( ) ) {
2024-01-18 16:58:22 -03:00
form ( ) - > submit_form ( * this , { . user_involvement = user_navigation_involvement ( event ) } ) . release_value_but_fixme_should_propagate_errors ( ) ;
2025-02-26 20:53:48 -03:00
return ;
2025-02-12 13:58:03 -03:00
}
2025-02-26 20:53:48 -03:00
// 2. If element's type attribute is in the Reset Button state, then reset element's form owner, and return.
2025-02-12 13:58:03 -03:00
if ( type_state ( ) = = TypeAttributeState : : Reset ) {
2024-01-18 16:58:22 -03:00
form ( ) - > reset_form ( ) ;
2025-02-26 20:53:48 -03:00
return ;
2024-01-18 16:58:22 -03:00
}
2025-02-26 20:53:48 -03:00
// 3. If element's type attribute is in the Auto state, then return.
if ( type_state ( ) = = TypeAttributeState : : Auto )
return ;
2023-11-18 06:48:09 -03:00
}
2024-01-18 16:58:22 -03:00
2025-02-20 14:01:28 -03:00
// FIXME: 4. Let target be the result of running element's get the commandfor associated element.
// FIXME: 5. If target is not null:
// ...
// 6. Otherwise, run the popover target attribute activation behavior given element and event's target.
2025-01-14 01:15:38 -03:00
if ( event . target ( ) & & event . target ( ) - > is_dom_node ( ) )
PopoverInvokerElement : : popover_target_activation_behaviour ( * this , as < DOM : : Node > ( * event . target ( ) ) ) ;
2023-11-18 06:48:09 -03:00
}
2025-02-25 05:43:11 -03:00
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-cva-willvalidate
bool HTMLButtonElement : : will_validate ( )
{
// The willValidate attribute's getter must return true, if this element is a candidate for constraint validation
return is_candidate_for_constraint_validation ( ) ;
}
2024-11-02 15:17:20 -03:00
bool HTMLButtonElement : : is_focusable ( ) const
{
return enabled ( ) ;
}
2025-04-03 20:16:44 -03:00
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-button-command
String HTMLButtonElement : : command ( ) const
{
// 1. Let command be this's command attribute.
auto command = get_attribute ( AttributeNames : : command ) ;
// https://html.spec.whatwg.org/multipage/form-elements.html#attr-button-command
// The command attribute is an enumerated attribute with the following keywords and states:
// Keyword State Brief description
// toggle-popover Toggle Popover Shows or hides the targeted popover element.
// show-popover Show Popover Shows the targeted popover element.
// hide-popover Hide Popover Hides the targeted popover element.
// close Close Closes the targeted dialog element.
// show-modal Show Modal Opens the targeted dialog element as modal.
// A custom command keyword Custom Only dispatches the command event on the targeted element.
Array valid_values { " toggle-popover " _string , " show-popover " _string , " hide-popover " _string , " close " _string , " show-modal " _string } ;
// 2. If command is in the Custom state, then return command's value.
// A custom command keyword is a string that starts with "--".
if ( command . has_value ( ) & & command . value ( ) . starts_with_bytes ( " -- " sv ) ) {
return command . value ( ) ;
}
// NOTE: Steps are re-ordered a bit.
// 4. Return the keword corresponding to the value of command.return
if ( command . has_value ( ) ) {
auto command_value = command . value ( ) ;
for ( auto const & value : valid_values ) {
if ( value . equals_ignoring_ascii_case ( command_value ) ) {
return value ;
}
}
}
// 3. If command is in the Unknown state, then return the empty string.
// The attribute's missing value default and invalid value default are both the Unknown state.
return { } ;
}
// https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:dom-button-command-2
WebIDL : : ExceptionOr < void > HTMLButtonElement : : set_command ( String const & value )
{
return set_attribute ( AttributeNames : : command , value ) ;
}
2020-07-31 23:04:26 -03:00
}