2020-01-18 09:38:21 +01:00
/*
2022-02-15 19:16:57 +01:00
* Copyright ( c ) 2018 - 2022 , Andreas Kling < kling @ serenityos . org >
2022-02-17 21:22:36 +00:00
* Copyright ( c ) 2022 , Adam Hodgen < ant1441 @ gmail . com >
2022-10-03 23:39:53 -06:00
* Copyright ( c ) 2022 , Andrew Kaster < akaster @ serenityos . org >
2020-01-18 09:38:21 +01:00
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 09:38:21 +01:00
*/
2020-03-07 10:32:51 +01:00
# include <LibWeb/DOM/Document.h>
2020-05-30 11:59:10 +02:00
# include <LibWeb/DOM/Event.h>
2021-02-10 18:26:07 +01:00
# include <LibWeb/DOM/ShadowRoot.h>
# include <LibWeb/DOM/Text.h>
2021-11-18 15:01:28 +01:00
# include <LibWeb/HTML/BrowsingContext.h>
2020-11-21 19:15:57 +00:00
# include <LibWeb/HTML/EventNames.h>
2020-07-26 15:08:16 +02:00
# include <LibWeb/HTML/HTMLFormElement.h>
# include <LibWeb/HTML/HTMLInputElement.h>
2022-10-03 23:39:53 -06:00
# include <LibWeb/HTML/Scripting/Environments.h>
2022-10-01 18:25:29 +01:00
# include <LibWeb/Infra/CharacterTypes.h>
2021-10-06 20:02:41 +02:00
# include <LibWeb/Layout/BlockContainer.h>
2020-11-22 15:53:01 +01:00
# include <LibWeb/Layout/ButtonBox.h>
# include <LibWeb/Layout/CheckBox.h>
2021-04-03 09:07:45 -04:00
# include <LibWeb/Layout/RadioButton.h>
2022-10-03 23:39:53 -06:00
# include <LibWeb/WebIDL/DOMException.h>
# include <LibWeb/WebIDL/ExceptionOr.h>
2019-11-25 21:21:55 +01:00
2020-07-28 18:20:36 +02:00
namespace Web : : HTML {
2020-03-07 10:27:02 +01:00
2022-02-18 21:00:52 +01:00
HTMLInputElement : : HTMLInputElement ( DOM : : Document & document , DOM : : QualifiedName qualified_name )
2022-03-23 18:55:54 -04:00
: HTMLElement ( document , move ( qualified_name ) )
2022-12-04 18:02:33 +00:00
, m_value ( DeprecatedString : : empty ( ) )
2019-11-25 21:21:55 +01:00
{
2022-03-14 23:05:55 +00:00
activation_behavior = [ this ] ( auto & ) {
// The activation behavior for input elements are these steps:
2019-11-25 21:21:55 +01:00
2022-03-14 23:05:55 +00:00
// FIXME: 1. If this element is not mutable and is not in the Checkbox state and is not in the Radio state, then return.
2020-09-12 17:56:11 +02:00
2022-03-14 23:05:55 +00:00
// 2. Run this element's input activation behavior, if any, and do nothing otherwise.
2023-03-01 20:10:01 +01:00
run_input_activation_behavior ( ) . release_value_but_fixme_should_propagate_errors ( ) ;
2022-03-14 23:05:55 +00:00
} ;
2020-09-12 17:56:11 +02:00
}
2022-03-14 13:21:51 -06:00
HTMLInputElement : : ~ HTMLInputElement ( ) = default ;
2022-02-17 13:31:09 +01:00
2023-01-28 12:33:35 -05:00
JS : : ThrowCompletionOr < void > HTMLInputElement : : initialize ( JS : : Realm & realm )
2023-01-10 06:28:20 -05:00
{
2023-01-28 12:33:35 -05:00
MUST_OR_THROW_OOM ( Base : : initialize ( realm ) ) ;
2023-01-10 06:28:20 -05:00
set_prototype ( & Bindings : : ensure_web_prototype < Bindings : : HTMLInputElementPrototype > ( realm , " HTMLInputElement " ) ) ;
2023-01-28 12:33:35 -05:00
return { } ;
2023-01-10 06:28:20 -05:00
}
2022-08-28 13:42:07 +02:00
void HTMLInputElement : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
visitor . visit ( m_text_node . ptr ( ) ) ;
visitor . visit ( m_legacy_pre_activation_behavior_checked_element_in_group . ptr ( ) ) ;
2022-10-03 23:39:53 -06:00
visitor . visit ( m_selected_files ) ;
2022-08-28 13:42:07 +02:00
}
2022-10-17 14:41:50 +02:00
JS : : GCPtr < Layout : : Node > HTMLInputElement : : create_layout_node ( NonnullRefPtr < CSS : : StyleProperties > style )
2019-11-25 21:21:55 +01:00
{
2022-03-15 12:14:54 +00:00
if ( type_state ( ) = = TypeAttributeState : : Hidden )
2020-05-04 22:33:49 +02:00
return nullptr ;
2022-10-03 23:39:53 -06:00
if ( type_state ( ) = = TypeAttributeState : : SubmitButton | | type_state ( ) = = TypeAttributeState : : Button | | type_state ( ) = = TypeAttributeState : : ResetButton | | type_state ( ) = = TypeAttributeState : : FileUpload )
2022-10-17 14:41:50 +02:00
return heap ( ) . allocate_without_realm < Layout : : ButtonBox > ( document ( ) , * this , move ( style ) ) ;
2020-09-12 17:56:11 +02:00
2022-03-15 12:14:54 +00:00
if ( type_state ( ) = = TypeAttributeState : : Checkbox )
2022-10-17 14:41:50 +02:00
return heap ( ) . allocate_without_realm < Layout : : CheckBox > ( document ( ) , * this , move ( style ) ) ;
2019-11-25 21:21:55 +01:00
2022-03-15 12:14:54 +00:00
if ( type_state ( ) = = TypeAttributeState : : RadioButton )
2022-10-17 14:41:50 +02:00
return heap ( ) . allocate_without_realm < Layout : : RadioButton > ( document ( ) , * this , move ( style ) ) ;
2021-04-03 09:07:45 -04:00
2022-10-17 14:41:50 +02:00
return heap ( ) . allocate_without_realm < Layout : : BlockContainer > ( document ( ) , this , move ( style ) ) ;
2019-11-25 21:21:55 +01:00
}
2020-03-07 10:27:02 +01:00
2022-03-14 23:05:55 +00:00
void HTMLInputElement : : set_checked ( bool checked , ChangeSource change_source )
2020-09-11 18:17:39 +02:00
{
if ( m_checked = = checked )
return ;
2022-02-15 19:16:57 +01:00
// The dirty checkedness flag must be initially set to false when the element is created,
// and must be set to true whenever the user interacts with the control in a way that changes the checkedness.
if ( change_source = = ChangeSource : : User )
m_dirty_checkedness = true ;
2020-09-11 18:17:39 +02:00
m_checked = checked ;
2022-03-12 23:58:19 +01:00
set_needs_style_update ( true ) ;
2022-02-15 19:16:57 +01:00
}
2022-03-15 01:13:05 +00:00
void HTMLInputElement : : set_checked_binding ( bool checked )
{
2022-03-15 12:14:54 +00:00
if ( type_state ( ) = = TypeAttributeState : : RadioButton ) {
2022-03-15 01:13:05 +00:00
if ( checked )
set_checked_within_group ( ) ;
else
set_checked ( false , ChangeSource : : Programmatic ) ;
} else {
set_checked ( checked , ChangeSource : : Programmatic ) ;
}
}
2022-10-03 23:39:53 -06:00
// https://html.spec.whatwg.org/multipage/input.html#dom-input-files
JS : : GCPtr < FileAPI : : FileList > HTMLInputElement : : files ( )
{
// On getting, if the IDL attribute applies, it must return a FileList object that represents the current selected files.
// The same object must be returned until the list of selected files changes.
// If the IDL attribute does not apply, then it must instead return null.
if ( m_type ! = TypeAttributeState : : FileUpload )
return nullptr ;
if ( ! m_selected_files )
2023-02-14 19:57:46 +01:00
m_selected_files = FileAPI : : FileList : : create ( realm ( ) , { } ) . release_value_but_fixme_should_propagate_errors ( ) ;
2022-10-03 23:39:53 -06:00
return m_selected_files ;
}
// https://html.spec.whatwg.org/multipage/input.html#dom-input-files
void HTMLInputElement : : set_files ( JS : : GCPtr < FileAPI : : FileList > files )
{
// 1. If the IDL attribute does not apply or the given value is null, then return.
if ( m_type ! = TypeAttributeState : : FileUpload | | files = = nullptr )
return ;
// 2. Replace the element's selected files with the given value.
m_selected_files = files ;
}
// https://html.spec.whatwg.org/multipage/input.html#update-the-file-selection
void HTMLInputElement : : update_the_file_selection ( JS : : NonnullGCPtr < FileAPI : : FileList > files )
{
// 1. Queue an element task on the user interaction task source given element and the following steps:
2022-11-19 01:09:53 +00:00
queue_an_element_task ( Task : : Source : : UserInteraction , [ this , files ] {
2022-10-03 23:39:53 -06:00
// 1. Update element's selected files so that it represents the user's selection.
this - > set_files ( files . ptr ( ) ) ;
// 2. Fire an event named input at the input element, with the bubbles and composed attributes initialized to true.
2023-02-14 22:43:17 +01:00
auto input_event = DOM : : Event : : create ( this - > realm ( ) , EventNames : : input , { . bubbles = true , . composed = true } ) . release_value_but_fixme_should_propagate_errors ( ) ;
this - > dispatch_event ( input_event ) ;
2022-10-03 23:39:53 -06:00
// 3. Fire an event named change at the input element, with the bubbles attribute initialized to true.
2023-02-14 22:43:17 +01:00
auto change_event = DOM : : Event : : create ( this - > realm ( ) , EventNames : : change , { . bubbles = true } ) . release_value_but_fixme_should_propagate_errors ( ) ;
this - > dispatch_event ( change_event ) ;
2022-10-03 23:39:53 -06:00
} ) ;
}
// https://html.spec.whatwg.org/multipage/input.html#show-the-picker,-if-applicable
static void show_the_picker_if_applicable ( HTMLInputElement & element )
{
// To show the picker, if applicable for an input element element:
// 1. If element's relevant global object does not have transient activation, then return.
auto & global_object = relevant_global_object ( element ) ;
if ( ! is < HTML : : Window > ( global_object ) | | ! static_cast < HTML : : Window & > ( global_object ) . has_transient_activation ( ) )
return ;
// FIXME: 2. If element is not mutable, then return.
// 3. If element's type attribute is in the File Upload state, then run these steps in parallel:
if ( element . type_state ( ) = = HTMLInputElement : : TypeAttributeState : : FileUpload ) {
// NOTE: These steps cannot be fully implemented here, and must be done in the PageClient when the response comes back from the PageHost
// 1. Optionally, wait until any prior execution of this algorithm has terminated.
// 2. Display a prompt to the user requesting that the user specify some files.
// If the multiple attribute is not set on element, there must be no more than one file selected; otherwise, any number may be selected.
// Files can be from the filesystem or created on the fly, e.g., a picture taken from a camera connected to the user's device.
// 3. Wait for the user to have made their selection.
// 4. If the user dismissed the prompt without changing their selection,
// then queue an element task on the user interaction task source given element to fire an event named cancel at element,
// with the bubbles attribute initialized to true.
// 5. Otherwise, update the file selection for element.
bool const multiple = element . has_attribute ( HTML : : AttributeNames : : multiple ) ;
auto weak_element = element . make_weak_ptr < DOM : : EventTarget > ( ) ;
// FIXME: Pass along accept attribute information https://html.spec.whatwg.org/multipage/input.html#attr-input-accept
// The accept attribute may be specified to provide user agents with a hint of what file types will be accepted.
element . document ( ) . browsing_context ( ) - > top_level_browsing_context ( ) . page ( ) - > client ( ) . page_did_request_file_picker ( weak_element , multiple ) ;
return ;
}
// FIXME: show "any relevant user interface" for other type attribute states "in the way [the user agent] normally would"
// 4. Otherwise, the user agent should show any relevant user interface for selecting a value for element,
// in the way it normally would when the user interacts with the control. (If no such UI applies to element, then this step does nothing.)
// If such a user interface is shown, it must respect the requirements stated in the relevant parts of the specification for how element
// behaves given its type attribute state. (For example, various sections describe restrictions on the resulting value string.)
// This step can have side effects, such as closing other pickers that were previously shown by this algorithm.
// (If this closes a file selection picker, then per the above that will lead to firing either input and change events, or a cancel event.)
}
// https://html.spec.whatwg.org/multipage/input.html#dom-input-showpicker
WebIDL : : ExceptionOr < void > HTMLInputElement : : show_picker ( )
{
// The showPicker() method steps are:
// FIXME: 1. If this is not mutable, then throw an "InvalidStateError" DOMException.
// 2. If this's relevant settings object's origin is not same origin with this's relevant settings object's top-level origin,
// and this's type attribute is not in the File Upload state or Color state, then throw a "SecurityError" DOMException.
// NOTE: File and Color inputs are exempted from this check for historical reason: their input activation behavior also shows their pickers,
// and has never been guarded by an origin check.
if ( ! relevant_settings_object ( * this ) . origin ( ) . is_same_origin ( relevant_settings_object ( * this ) . top_level_origin )
& & m_type ! = TypeAttributeState : : FileUpload & & m_type ! = TypeAttributeState : : Color ) {
return WebIDL : : SecurityError : : create ( realm ( ) , " Cross origin pickers are not allowed " sv ) ;
}
// 3. If this's relevant global object does not have transient activation, then throw a "NotAllowedError" DOMException.
// FIXME: The global object we get here should probably not need casted to Window to check for transient activation
auto & global_object = relevant_global_object ( * this ) ;
if ( ! is < HTML : : Window > ( global_object ) | | ! static_cast < HTML : : Window & > ( global_object ) . has_transient_activation ( ) ) {
return WebIDL : : NotAllowedError : : create ( realm ( ) , " Too long since user activation to show picker " sv ) ;
}
// 4. Show the picker, if applicable, for this.
show_the_picker_if_applicable ( * this ) ;
return { } ;
}
2022-02-15 19:16:57 +01:00
// https://html.spec.whatwg.org/multipage/input.html#input-activation-behavior
2023-03-01 20:10:01 +01:00
ErrorOr < void > HTMLInputElement : : run_input_activation_behavior ( )
2022-02-15 19:16:57 +01:00
{
2022-03-15 12:14:54 +00:00
if ( type_state ( ) = = TypeAttributeState : : Checkbox | | type_state ( ) = = TypeAttributeState : : RadioButton ) {
2022-02-15 21:58:13 +01:00
// 1. If the element is not connected, then return.
if ( ! is_connected ( ) )
2023-03-01 20:10:01 +01:00
return { } ;
2022-02-15 21:58:13 +01:00
// 2. Fire an event named input at the element with the bubbles and composed attributes initialized to true.
2023-02-14 22:43:17 +01:00
auto input_event = DOM : : Event : : create ( realm ( ) , HTML : : EventNames : : input ) . release_value_but_fixme_should_propagate_errors ( ) ;
2022-02-15 21:58:13 +01:00
input_event - > set_bubbles ( true ) ;
input_event - > set_composed ( true ) ;
2023-02-14 22:43:17 +01:00
dispatch_event ( input_event ) ;
2022-02-15 21:58:13 +01:00
// 3. Fire an event named change at the element with the bubbles attribute initialized to true.
2023-02-14 22:43:17 +01:00
auto change_event = DOM : : Event : : create ( realm ( ) , HTML : : EventNames : : change ) . release_value_but_fixme_should_propagate_errors ( ) ;
2022-02-15 21:58:13 +01:00
change_event - > set_bubbles ( true ) ;
2022-08-08 22:29:40 +02:00
dispatch_event ( * change_event ) ;
2022-03-15 12:14:54 +00:00
} else if ( type_state ( ) = = TypeAttributeState : : SubmitButton ) {
2022-08-28 13:42:07 +02:00
JS : : GCPtr < HTMLFormElement > form ;
2022-03-14 23:05:55 +00:00
// 1. If the element does not have a form owner, then return.
if ( ! ( form = this - > form ( ) ) )
2023-03-01 20:10:01 +01:00
return { } ;
2022-03-14 23:05:55 +00:00
// 2. If the element's node document is not fully active, then return.
if ( ! document ( ) . is_fully_active ( ) )
2023-03-01 20:10:01 +01:00
return { } ;
2022-03-14 23:05:55 +00:00
// 3. Submit the form owner from the element.
2023-03-01 20:10:01 +01:00
TRY ( form - > submit_form ( this ) ) ;
2022-10-03 23:39:53 -06:00
} else if ( type_state ( ) = = TypeAttributeState : : FileUpload ) {
show_the_picker_if_applicable ( * this ) ;
2022-02-15 21:58:13 +01:00
} else {
2023-02-14 22:43:17 +01:00
dispatch_event ( DOM : : Event : : create ( realm ( ) , EventNames : : change ) . release_value_but_fixme_should_propagate_errors ( ) ) ;
2022-02-15 21:58:13 +01:00
}
2023-03-01 20:10:01 +01:00
return { } ;
2020-09-11 18:17:39 +02:00
}
2022-02-17 12:59:32 +01:00
void HTMLInputElement : : did_edit_text_node ( Badge < BrowsingContext > )
{
2022-03-22 10:55:13 -04:00
// An input element's dirty value flag must be set to true whenever the user interacts with the control in a way that changes the value.
m_value = value_sanitization_algorithm ( m_text_node - > data ( ) ) ;
m_dirty_value = true ;
2022-02-17 12:59:32 +01:00
// NOTE: This is a bit ad-hoc, but basically implements part of "4.10.5.5 Common event behaviors"
// https://html.spec.whatwg.org/multipage/input.html#common-input-element-events
queue_an_element_task ( HTML : : Task : : Source : : UserInteraction , [ this ] {
2023-02-14 22:43:17 +01:00
auto input_event = DOM : : Event : : create ( realm ( ) , HTML : : EventNames : : input ) . release_value_but_fixme_should_propagate_errors ( ) ;
2022-02-17 12:59:32 +01:00
input_event - > set_bubbles ( true ) ;
input_event - > set_composed ( true ) ;
2022-08-08 22:29:40 +02:00
dispatch_event ( * input_event ) ;
2022-02-17 12:59:32 +01:00
// FIXME: This should only fire when the input is "committed", whatever that means.
2023-02-14 22:43:17 +01:00
auto change_event = DOM : : Event : : create ( realm ( ) , HTML : : EventNames : : change ) . release_value_but_fixme_should_propagate_errors ( ) ;
2022-02-17 12:59:32 +01:00
change_event - > set_bubbles ( true ) ;
2023-02-14 22:43:17 +01:00
dispatch_event ( change_event ) ;
2022-02-17 12:59:32 +01:00
} ) ;
}
2022-12-04 18:02:33 +00:00
DeprecatedString HTMLInputElement : : value ( ) const
2021-02-10 18:26:07 +01:00
{
2022-10-03 23:39:53 -06:00
// https://html.spec.whatwg.org/multipage/input.html#dom-input-value-filename
if ( type_state ( ) = = TypeAttributeState : : FileUpload ) {
// NOTE: This "fakepath" requirement is a sad accident of history. See the example in the File Upload state section for more information.
// NOTE: Since path components are not permitted in filenames in the list of selected files, the "\fakepath\" cannot be mistaken for a path component.
if ( m_selected_files & & m_selected_files - > item ( 0 ) )
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " C: \\ fakepath \\ {} " , m_selected_files - > item ( 0 ) - > name ( ) ) ;
2022-10-03 23:39:53 -06:00
return " C: \\ fakepath \\ " sv ;
}
// https://html.spec.whatwg.org/multipage/input.html#dom-input-value-value
2022-03-22 10:55:13 -04:00
// Return the current value of the element.
return m_value ;
2021-02-10 18:26:07 +01:00
}
2022-12-04 18:02:33 +00:00
WebIDL : : ExceptionOr < void > HTMLInputElement : : set_value ( DeprecatedString value )
2021-02-10 18:26:07 +01:00
{
2022-10-03 23:39:53 -06:00
// https://html.spec.whatwg.org/multipage/input.html#dom-input-value-filename
if ( type_state ( ) = = TypeAttributeState : : FileUpload ) {
// On setting, if the new value is the empty string, empty the list of selected files; otherwise, throw an "InvalidStateError" DOMException.
2022-12-04 18:02:33 +00:00
if ( value ! = DeprecatedString : : empty ( ) )
2022-10-03 23:39:53 -06:00
return WebIDL : : InvalidStateError : : create ( realm ( ) , " Setting value of input type file to non-empty string " sv ) ;
m_selected_files = nullptr ;
return { } ;
}
// https://html.spec.whatwg.org/multipage/input.html#dom-input-value-value
2022-03-22 10:55:13 -04:00
// 1. Let oldValue be the element's value.
auto old_value = move ( m_value ) ;
2022-02-17 23:05:46 +00:00
2022-03-22 10:55:13 -04:00
// 2. Set the element's value to the new value.
// NOTE: This is done as part of step 4 below.
// 3. Set the element's dirty value flag to true.
m_dirty_value = true ;
// 4. Invoke the value sanitization algorithm, if the element's type attribute's current state defines one.
m_value = value_sanitization_algorithm ( move ( value ) ) ;
// 5. If the element's value (after applying the value sanitization algorithm) is different from oldValue,
// and the element has a text entry cursor position, move the text entry cursor position to the end of the
// text control, unselecting any selected text and resetting the selection direction to "none".
if ( m_text_node & & ( m_value ! = old_value ) )
m_text_node - > set_data ( m_value ) ;
2022-10-03 23:39:53 -06:00
return { } ;
2021-02-10 18:26:07 +01:00
}
2022-11-30 22:15:12 -05:00
// https://html.spec.whatwg.org/multipage/input.html#the-input-element:attr-input-placeholder-3
static bool is_allowed_to_have_placeholder ( HTML : : HTMLInputElement : : TypeAttributeState state )
{
switch ( state ) {
case HTML : : HTMLInputElement : : TypeAttributeState : : Text :
case HTML : : HTMLInputElement : : TypeAttributeState : : Search :
case HTML : : HTMLInputElement : : TypeAttributeState : : URL :
case HTML : : HTMLInputElement : : TypeAttributeState : : Telephone :
case HTML : : HTMLInputElement : : TypeAttributeState : : Email :
case HTML : : HTMLInputElement : : TypeAttributeState : : Password :
case HTML : : HTMLInputElement : : TypeAttributeState : : Number :
return true ;
default :
return false ;
}
}
// https://html.spec.whatwg.org/multipage/input.html#attr-input-placeholder
2022-12-04 18:02:33 +00:00
Optional < DeprecatedString > HTMLInputElement : : placeholder_value ( ) const
2022-11-30 22:15:12 -05:00
{
if ( ! m_text_node | | ! m_text_node - > data ( ) . is_empty ( ) )
return { } ;
if ( ! is_allowed_to_have_placeholder ( type_state ( ) ) )
return { } ;
if ( ! has_attribute ( HTML : : AttributeNames : : placeholder ) )
return { } ;
auto placeholder = attribute ( HTML : : AttributeNames : : placeholder ) ;
if ( placeholder . contains ( ' \r ' ) | | placeholder . contains ( ' \n ' ) ) {
StringBuilder builder ;
for ( auto ch : placeholder ) {
if ( ch ! = ' \r ' & & ch ! = ' \n ' )
builder . append ( ch ) ;
}
2022-12-06 01:12:49 +00:00
placeholder = builder . to_deprecated_string ( ) ;
2022-11-30 22:15:12 -05:00
}
return placeholder ;
}
2021-02-10 18:26:07 +01:00
void HTMLInputElement : : create_shadow_tree_if_needed ( )
{
if ( shadow_root ( ) )
return ;
2022-03-16 00:25:28 +01:00
// FIXME: This could be better factored. Everything except the below types becomes a text input.
switch ( type_state ( ) ) {
case TypeAttributeState : : RadioButton :
case TypeAttributeState : : Checkbox :
case TypeAttributeState : : Button :
case TypeAttributeState : : SubmitButton :
case TypeAttributeState : : ResetButton :
case TypeAttributeState : : ImageButton :
return ;
default :
break ;
}
2023-01-28 20:36:58 +01:00
auto shadow_root = heap ( ) . allocate < DOM : : ShadowRoot > ( realm ( ) , document ( ) , * this , Bindings : : ShadowRootMode : : Closed ) . release_allocated_value_but_fixme_should_propagate_errors ( ) ;
2022-03-22 10:55:13 -04:00
auto initial_value = m_value ;
2021-02-10 18:26:07 +01:00
if ( initial_value . is_null ( ) )
2022-12-04 18:02:33 +00:00
initial_value = DeprecatedString : : empty ( ) ;
2022-02-26 10:00:49 +01:00
auto element = document ( ) . create_element ( HTML : : TagNames : : div ) . release_value ( ) ;
2022-10-30 17:50:04 +00:00
MUST ( element - > set_attribute ( HTML : : AttributeNames : : style , " white-space: pre; padding-top: 1px; padding-bottom: 1px; padding-left: 2px; padding-right: 2px " ) ) ;
2023-01-28 13:39:44 -05:00
m_text_node = heap ( ) . allocate < DOM : : Text > ( realm ( ) , document ( ) , initial_value ) . release_allocated_value_but_fixme_should_propagate_errors ( ) ;
2022-10-03 23:39:53 -06:00
m_text_node - > set_always_editable ( m_type ! = TypeAttributeState : : FileUpload ) ;
2022-02-17 12:59:32 +01:00
m_text_node - > set_owner_input_element ( { } , * this ) ;
2022-11-05 17:19:00 +01:00
if ( m_type = = TypeAttributeState : : Password )
m_text_node - > set_is_password_input ( { } , true ) ;
2022-10-30 17:50:04 +00:00
MUST ( element - > append_child ( * m_text_node ) ) ;
2022-12-14 17:40:33 +00:00
MUST ( shadow_root - > append_child ( element ) ) ;
set_shadow_root ( shadow_root ) ;
2021-02-10 18:26:07 +01:00
}
2022-02-06 19:27:10 +01:00
void HTMLInputElement : : did_receive_focus ( )
{
auto * browsing_context = document ( ) . browsing_context ( ) ;
if ( ! browsing_context )
return ;
if ( ! m_text_node )
return ;
browsing_context - > set_cursor_position ( DOM : : Position { * m_text_node , 0 } ) ;
}
2023-01-08 19:23:00 -05:00
void HTMLInputElement : : parse_attribute ( DeprecatedFlyString const & name , DeprecatedString const & value )
2022-02-15 19:16:57 +01:00
{
2022-03-23 18:55:54 -04:00
HTMLElement : : parse_attribute ( name , value ) ;
2022-02-15 19:16:57 +01:00
if ( name = = HTML : : AttributeNames : : checked ) {
// When the checked content attribute is added, if the control does not have dirty checkedness,
// the user agent must set the checkedness of the element to true
if ( ! m_dirty_checkedness )
2022-03-14 23:05:55 +00:00
set_checked ( true , ChangeSource : : Programmatic ) ;
2022-03-16 07:44:21 -04:00
} else if ( name = = HTML : : AttributeNames : : type ) {
m_type = parse_type_attribute ( value ) ;
2022-03-22 10:55:13 -04:00
} else if ( name = = HTML : : AttributeNames : : value ) {
if ( ! m_dirty_value )
m_value = value_sanitization_algorithm ( value ) ;
2022-02-15 19:16:57 +01:00
}
}
2022-03-16 07:44:21 -04:00
HTMLInputElement : : TypeAttributeState HTMLInputElement : : parse_type_attribute ( StringView type )
{
# define __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(keyword, state) \
2022-07-11 17:32:29 +00:00
if ( type . equals_ignoring_case ( # keyword # # sv ) ) \
2022-03-16 07:44:21 -04:00
return HTMLInputElement : : TypeAttributeState : : state ;
ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTES
# undef __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE
// The missing value default and the invalid value default are the Text state.
// https://html.spec.whatwg.org/multipage/input.html#the-input-element:missing-value-default
// https://html.spec.whatwg.org/multipage/input.html#the-input-element:invalid-value-default
return HTMLInputElement : : TypeAttributeState : : Text ;
}
2023-01-08 19:23:00 -05:00
void HTMLInputElement : : did_remove_attribute ( DeprecatedFlyString const & name )
2022-02-15 19:16:57 +01:00
{
2022-03-23 18:55:54 -04:00
HTMLElement : : did_remove_attribute ( name ) ;
2022-02-15 19:16:57 +01:00
if ( name = = HTML : : AttributeNames : : checked ) {
// When the checked content attribute is removed, if the control does not have dirty checkedness,
// the user agent must set the checkedness of the element to false.
if ( ! m_dirty_checkedness )
2022-03-14 23:05:55 +00:00
set_checked ( false , ChangeSource : : Programmatic ) ;
2022-03-22 10:55:13 -04:00
} else if ( name = = HTML : : AttributeNames : : value ) {
if ( ! m_dirty_value )
2022-12-04 18:02:33 +00:00
m_value = DeprecatedString : : empty ( ) ;
2022-02-15 19:16:57 +01:00
}
}
2022-12-04 18:02:33 +00:00
DeprecatedString HTMLInputElement : : type ( ) const
2022-02-17 13:12:01 +01:00
{
2022-03-16 07:46:17 -04:00
switch ( m_type ) {
2022-02-17 23:05:46 +00:00
# define __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE(keyword, state) \
2022-03-16 07:46:17 -04:00
case TypeAttributeState : : state : \
return # keyword # # sv ;
ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTES
2022-02-17 23:05:46 +00:00
# undef __ENUMERATE_HTML_INPUT_TYPE_ATTRIBUTE
2022-03-16 07:46:17 -04:00
}
2022-02-17 23:05:46 +00:00
2022-03-16 07:46:17 -04:00
VERIFY_NOT_REACHED ( ) ;
2022-02-17 23:05:46 +00:00
}
2022-12-04 18:02:33 +00:00
void HTMLInputElement : : set_type ( DeprecatedString const & type )
2022-02-17 13:12:01 +01:00
{
2022-10-30 17:50:04 +00:00
MUST ( set_attribute ( HTML : : AttributeNames : : type , type ) ) ;
2022-02-17 13:12:01 +01:00
}
2022-12-03 23:10:45 -06:00
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-simple-colour
static bool is_valid_simple_color ( DeprecatedString const & value )
{
// if it is exactly seven characters long,
if ( value . length ( ) ! = 7 )
return false ;
// and the first character is a U+0023 NUMBER SIGN character (#),
if ( ! value . starts_with ( ' # ' ) )
return false ;
// and the remaining six characters are all ASCII hex digits
for ( size_t i = 1 ; i < value . length ( ) ; i + + )
if ( ! is_ascii_hex_digit ( value [ i ] ) )
return false ;
return true ;
}
2022-12-04 22:29:47 -06:00
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-time-string
static bool is_valid_time_string ( DeprecatedString const & value )
{
// A string is a valid time string representing an hour hour, a minute minute, and a second second if it consists of the following components in the given order:
// 1. Two ASCII digits, representing hour, in the range 0 ≤ hour ≤ 23
// 2. A U+003A COLON character (:)
// 3. Two ASCII digits, representing minute, in the range 0 ≤ minute ≤ 59
// 4. If second is nonzero, or optionally if second is zero:
// 1. A U+003A COLON character (:)
// 2. Two ASCII digits, representing the integer part of second, in the range 0 ≤ s ≤ 59
// 3. If second is not an integer, or optionally if second is an integer:
// 1. A U+002E FULL STOP character (.)
// 2. One, two, or three ASCII digits, representing the fractional part of second
auto parts = value . split ( ' : ' ) ;
if ( parts . size ( ) ! = 2 | | parts . size ( ) ! = 3 )
return false ;
if ( parts [ 0 ] . length ( ) ! = 2 )
return false ;
auto hour = ( parse_ascii_digit ( parts [ 0 ] [ 0 ] ) * 10 ) + parse_ascii_digit ( parts [ 0 ] [ 1 ] ) ;
if ( hour > 23 )
return false ;
if ( parts [ 1 ] . length ( ) ! = 2 )
return false ;
auto minute = ( parse_ascii_digit ( parts [ 1 ] [ 0 ] ) * 10 ) + parse_ascii_digit ( parts [ 1 ] [ 1 ] ) ;
if ( minute > 59 )
return false ;
if ( parts . size ( ) = = 2 )
return true ;
if ( parts [ 2 ] . length ( ) < 2 )
return false ;
auto second = ( parse_ascii_digit ( parts [ 2 ] [ 0 ] ) * 10 ) + parse_ascii_digit ( parts [ 2 ] [ 1 ] ) ;
if ( second > 59 )
return false ;
if ( parts [ 2 ] . length ( ) = = 2 )
return true ;
auto second_parts = parts [ 2 ] . split ( ' . ' ) ;
if ( second_parts . size ( ) ! = 2 )
return false ;
if ( second_parts [ 1 ] . length ( ) < 1 | | second_parts [ 1 ] . length ( ) > 3 )
return false ;
for ( auto digit : second_parts [ 1 ] )
if ( ! is_ascii_digit ( digit ) )
return false ;
return true ;
}
2022-12-04 00:22:00 -06:00
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#week-number-of-the-last-day
static u32 week_number_of_the_last_day ( u64 )
{
// FIXME: sometimes return 53 (!)
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#weeks
return 52 ;
}
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-week-string
static bool is_valid_week_string ( DeprecatedString const & value )
{
// A string is a valid week string representing a week-year year and week week if it consists of the following components in the given order:
// 1. Four or more ASCII digits, representing year, where year > 0
// 2. A U+002D HYPHEN-MINUS character (-)
// 3. A U+0057 LATIN CAPITAL LETTER W character (W)
// 4. Two ASCII digits, representing the week week, in the range 1 ≤ week ≤ maxweek, where maxweek is the week number of the last day of week-year year
auto parts = value . split ( ' - ' ) ;
if ( parts . size ( ) ! = 2 )
return false ;
if ( parts [ 0 ] . length ( ) < 4 )
return false ;
for ( auto digit : parts [ 0 ] )
if ( ! is_ascii_digit ( digit ) )
return false ;
if ( parts [ 1 ] . length ( ) ! = 3 )
return false ;
if ( ! parts [ 1 ] . starts_with ( ' W ' ) )
return false ;
if ( ! is_ascii_digit ( parts [ 1 ] [ 1 ] ) )
return false ;
if ( ! is_ascii_digit ( parts [ 1 ] [ 2 ] ) )
return false ;
u64 year = 0 ;
for ( auto d : parts [ 0 ] ) {
year * = 10 ;
year + = parse_ascii_digit ( d ) ;
}
auto week = ( parse_ascii_digit ( parts [ 1 ] [ 1 ] ) * 10 ) + parse_ascii_digit ( parts [ 1 ] [ 2 ] ) ;
return week > = 1 & & week < = week_number_of_the_last_day ( year ) ;
}
2022-12-04 00:07:24 -06:00
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-month-string
static bool is_valid_month_string ( DeprecatedString const & value )
{
// A string is a valid month string representing a year year and month month if it consists of the following components in the given order:
// 1. Four or more ASCII digits, representing year, where year > 0
// 2. A U+002D HYPHEN-MINUS character (-)
// 3. Two ASCII digits, representing the month month, in the range 1 ≤ month ≤ 12
auto parts = value . split ( ' - ' ) ;
if ( parts . size ( ) ! = 2 )
return false ;
if ( parts [ 0 ] . length ( ) < 4 )
return false ;
for ( auto digit : parts [ 0 ] )
if ( ! is_ascii_digit ( digit ) )
return false ;
if ( parts [ 1 ] . length ( ) ! = 2 )
return false ;
if ( ! is_ascii_digit ( parts [ 1 ] [ 0 ] ) )
return false ;
if ( ! is_ascii_digit ( parts [ 1 ] [ 1 ] ) )
return false ;
auto month = ( parse_ascii_digit ( parts [ 1 ] [ 0 ] ) * 10 ) + parse_ascii_digit ( parts [ 1 ] [ 1 ] ) ;
return month > = 1 & & month < = 12 ;
}
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
static bool is_valid_date_string ( DeprecatedString const & value )
{
// A string is a valid date string representing a year year, month month, and day day if it consists of the following components in the given order:
// 1. A valid month string, representing year and month
// 2. A U+002D HYPHEN-MINUS character (-)
// 3. Two ASCII digits, representing day, in the range 1 ≤ day ≤ maxday where maxday is the number of days in the month month and year year
auto parts = value . split ( ' - ' ) ;
if ( parts . size ( ) ! = 3 )
return false ;
if ( ! is_valid_month_string ( DeprecatedString : : formatted ( " {}-{} " , parts [ 0 ] , parts [ 1 ] ) ) )
return false ;
if ( parts [ 2 ] . length ( ) ! = 2 )
return false ;
i64 year = 0 ;
for ( auto d : parts [ 0 ] ) {
year * = 10 ;
year + = parse_ascii_digit ( d ) ;
}
auto month = ( parse_ascii_digit ( parts [ 1 ] [ 0 ] ) * 10 ) + parse_ascii_digit ( parts [ 1 ] [ 1 ] ) ;
i64 day = ( parse_ascii_digit ( parts [ 2 ] [ 0 ] ) * 10 ) + parse_ascii_digit ( parts [ 2 ] [ 1 ] ) ;
return day > = 1 & & day < = AK : : days_in_month ( year , month ) ;
}
2022-12-04 22:41:55 -06:00
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-local-date-and-time-string
static bool is_valid_local_date_and_time_string ( DeprecatedString const & value )
{
auto parts_split_by_T = value . split ( ' T ' ) ;
if ( parts_split_by_T . size ( ) = = 2 )
return is_valid_date_string ( parts_split_by_T [ 0 ] ) & & is_valid_time_string ( parts_split_by_T [ 1 ] ) ;
auto parts_split_by_space = value . split ( ' ' ) ;
if ( parts_split_by_space . size ( ) = = 2 )
return is_valid_date_string ( parts_split_by_space [ 0 ] ) & & is_valid_time_string ( parts_split_by_space [ 1 ] ) ;
return false ;
}
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-normalised-local-date-and-time-string
static DeprecatedString normalize_local_date_and_time_string ( DeprecatedString const & value )
{
VERIFY ( value . count ( " " sv ) = = 1 ) ;
return value . replace ( " " sv , " T " sv , ReplaceMode : : FirstOnly ) ;
}
2022-02-17 23:05:46 +00:00
// https://html.spec.whatwg.org/multipage/input.html#value-sanitization-algorithm
2022-12-04 18:02:33 +00:00
DeprecatedString HTMLInputElement : : value_sanitization_algorithm ( DeprecatedString value ) const
2022-02-17 23:05:46 +00:00
{
if ( type_state ( ) = = HTMLInputElement : : TypeAttributeState : : Text | | type_state ( ) = = HTMLInputElement : : TypeAttributeState : : Search | | type_state ( ) = = HTMLInputElement : : TypeAttributeState : : Telephone | | type_state ( ) = = HTMLInputElement : : TypeAttributeState : : Password ) {
// Strip newlines from the value.
if ( value . contains ( ' \r ' ) | | value . contains ( ' \n ' ) ) {
StringBuilder builder ;
for ( auto c : value ) {
if ( ! ( c = = ' \r ' | | c = = ' \n ' ) )
builder . append ( c ) ;
}
2022-12-06 01:12:49 +00:00
return builder . to_deprecated_string ( ) ;
2022-02-17 23:05:46 +00:00
}
} else if ( type_state ( ) = = HTMLInputElement : : TypeAttributeState : : URL ) {
// Strip newlines from the value, then strip leading and trailing ASCII whitespace from the value.
if ( value . contains ( ' \r ' ) | | value . contains ( ' \n ' ) ) {
StringBuilder builder ;
for ( auto c : value ) {
if ( ! ( c = = ' \r ' | | c = = ' \n ' ) )
builder . append ( c ) ;
}
2022-10-01 18:25:29 +01:00
return builder . string_view ( ) . trim ( Infra : : ASCII_WHITESPACE ) ;
2022-02-17 23:05:46 +00:00
}
2022-12-03 23:15:30 -06:00
} else if ( type_state ( ) = = HTMLInputElement : : TypeAttributeState : : Email ) {
// https://html.spec.whatwg.org/multipage/input.html#email-state-(type=email):value-sanitization-algorithm
// FIXME: handle the `multiple` attribute
// Strip newlines from the value, then strip leading and trailing ASCII whitespace from the value.
if ( value . contains ( ' \r ' ) | | value . contains ( ' \n ' ) ) {
StringBuilder builder ;
for ( auto c : value ) {
if ( ! ( c = = ' \r ' | | c = = ' \n ' ) )
builder . append ( c ) ;
}
return builder . string_view ( ) . trim ( Infra : : ASCII_WHITESPACE ) ;
}
2022-02-17 23:05:46 +00:00
} else if ( type_state ( ) = = HTMLInputElement : : TypeAttributeState : : Number ) {
// If the value of the element is not a valid floating-point number, then set it to the empty string instead.
2022-10-12 02:24:05 +02:00
// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-floating-point-number-values
// 6. Skip ASCII whitespace within input given position.
auto maybe_double = value . to_double ( TrimWhitespace : : Yes ) ;
if ( ! maybe_double . has_value ( ) | | ! isfinite ( maybe_double . value ( ) ) )
2022-02-17 23:05:46 +00:00
return " " ;
2022-12-04 00:07:24 -06:00
} else if ( type_state ( ) = = HTMLInputElement : : TypeAttributeState : : Date ) {
// https://html.spec.whatwg.org/multipage/input.html#date-state-(type=date):value-sanitization-algorithm
if ( ! is_valid_date_string ( value ) )
return " " ;
2022-12-04 00:20:36 -06:00
} else if ( type_state ( ) = = HTMLInputElement : : TypeAttributeState : : Month ) {
// https://html.spec.whatwg.org/multipage/input.html#month-state-(type=month):value-sanitization-algorithm
if ( ! is_valid_month_string ( value ) )
return " " ;
2022-12-04 00:22:00 -06:00
} else if ( type_state ( ) = = HTMLInputElement : : TypeAttributeState : : Week ) {
// https://html.spec.whatwg.org/multipage/input.html#week-state-(type=week):value-sanitization-algorithm
if ( ! is_valid_week_string ( value ) )
return " " ;
2022-12-04 22:29:47 -06:00
} else if ( type_state ( ) = = HTMLInputElement : : TypeAttributeState : : Time ) {
// https://html.spec.whatwg.org/multipage/input.html#time-state-(type=time):value-sanitization-algorithm
if ( ! is_valid_time_string ( value ) )
return " " ;
2022-12-04 22:41:55 -06:00
} else if ( type_state ( ) = = HTMLInputElement : : TypeAttributeState : : LocalDateAndTime ) {
// https://html.spec.whatwg.org/multipage/input.html#local-date-and-time-state-(type=datetime-local):value-sanitization-algorithm
if ( is_valid_local_date_and_time_string ( value ) )
return normalize_local_date_and_time_string ( value ) ;
return " " ;
2022-12-04 22:48:36 -06:00
} else if ( type_state ( ) = = HTMLInputElement : : TypeAttributeState : : Range ) {
// https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range):value-sanitization-algorithm
auto maybe_double = value . to_double ( TrimWhitespace : : Yes ) ;
if ( ! maybe_double . has_value ( ) | | ! isfinite ( maybe_double . value ( ) ) )
2023-01-13 11:43:01 -05:00
return JS : : number_to_deprecated_string ( maybe_double . value_or ( 0 ) ) ;
2022-12-03 23:10:45 -06:00
} else if ( type_state ( ) = = HTMLInputElement : : TypeAttributeState : : Color ) {
// https://html.spec.whatwg.org/multipage/input.html#color-state-(type=color):value-sanitization-algorithm
// If the value of the element is a valid simple color, then set it to the value of the element converted to ASCII lowercase;
if ( is_valid_simple_color ( value ) )
return value . to_lowercase ( ) ;
// otherwise, set it to the string "#000000".
return " #000000 " ;
2022-02-17 23:05:46 +00:00
}
return value ;
}
2022-12-22 19:33:37 -05:00
// https://html.spec.whatwg.org/multipage/input.html#the-input-element:concept-form-reset-control
void HTMLInputElement : : reset_algorithm ( )
{
// The reset algorithm for input elements is to set the dirty value flag and dirty checkedness flag back to false,
m_dirty_value = false ;
m_dirty_checkedness = false ;
// set the value of the element to the value of the value content attribute, if there is one, or the empty string otherwise,
m_value = has_attribute ( AttributeNames : : value ) ? get_attribute ( AttributeNames : : value ) : DeprecatedString : : empty ( ) ;
// set the checkedness of the element to true if the element has a checked content attribute and false if it does not,
m_checked = has_attribute ( AttributeNames : : checked ) ;
// empty the list of selected files,
2023-02-14 19:57:46 +01:00
m_selected_files = FileAPI : : FileList : : create ( realm ( ) , { } ) . release_value_but_fixme_should_propagate_errors ( ) ;
2022-12-22 19:33:37 -05:00
// and then invoke the value sanitization algorithm, if the type attribute's current state defines one.
m_value = value_sanitization_algorithm ( m_value ) ;
if ( m_text_node )
m_text_node - > set_data ( m_value ) ;
}
2022-03-23 18:55:54 -04:00
void HTMLInputElement : : form_associated_element_was_inserted ( )
2022-03-14 20:23:18 +01:00
{
create_shadow_tree_if_needed ( ) ;
}
2022-03-14 23:05:55 +00:00
void HTMLInputElement : : set_checked_within_group ( )
{
if ( checked ( ) )
return ;
set_checked ( true , ChangeSource : : User ) ;
2022-12-04 18:02:33 +00:00
DeprecatedString name = this - > name ( ) ;
2022-03-14 23:05:55 +00:00
document ( ) . for_each_in_inclusive_subtree_of_type < HTML : : HTMLInputElement > ( [ & ] ( auto & element ) {
if ( element . checked ( ) & & & element ! = this & & element . name ( ) = = name )
element . set_checked ( false , ChangeSource : : User ) ;
return IterationDecision : : Continue ;
} ) ;
}
// https://html.spec.whatwg.org/multipage/input.html#the-input-element:legacy-pre-activation-behavior
void HTMLInputElement : : legacy_pre_activation_behavior ( )
{
m_before_legacy_pre_activation_behavior_checked = checked ( ) ;
// 1. If this element's type attribute is in the Checkbox state, then set
// this element's checkedness to its opposite value (i.e. true if it is
// false, false if it is true) and set this element's indeterminate IDL
// attribute to false.
// FIXME: Set indeterminate to false when that exists.
if ( type_state ( ) = = TypeAttributeState : : Checkbox ) {
set_checked ( ! checked ( ) , ChangeSource : : User ) ;
}
// 2. If this element's type attribute is in the Radio Button state, then
// get a reference to the element in this element's radio button group that
// has its checkedness set to true, if any, and then set this element's
// checkedness to true.
if ( type_state ( ) = = TypeAttributeState : : RadioButton ) {
2022-12-04 18:02:33 +00:00
DeprecatedString name = this - > name ( ) ;
2022-03-14 23:05:55 +00:00
document ( ) . for_each_in_inclusive_subtree_of_type < HTML : : HTMLInputElement > ( [ & ] ( auto & element ) {
if ( element . checked ( ) & & element . name ( ) = = name ) {
2022-08-28 13:42:07 +02:00
m_legacy_pre_activation_behavior_checked_element_in_group = & element ;
2022-03-14 23:05:55 +00:00
return IterationDecision : : Break ;
}
return IterationDecision : : Continue ;
} ) ;
set_checked_within_group ( ) ;
}
}
// https://html.spec.whatwg.org/multipage/input.html#the-input-element:legacy-canceled-activation-behavior
void HTMLInputElement : : legacy_cancelled_activation_behavior ( )
{
// 1. If the element's type attribute is in the Checkbox state, then set the
// element's checkedness and the element's indeterminate IDL attribute back
// to the values they had before the legacy-pre-activation behavior was run.
if ( type_state ( ) = = TypeAttributeState : : Checkbox ) {
set_checked ( m_before_legacy_pre_activation_behavior_checked , ChangeSource : : Programmatic ) ;
}
// 2. If this element 's type attribute is in the Radio Button state, then
// if the element to which a reference was obtained in the
// legacy-pre-activation behavior, if any, is still in what is now this
// element' s radio button group, if it still has one, and if so, setting
// that element 's checkedness to true; or else, if there was no such
// element, or that element is no longer in this element' s radio button
// group, or if this element no longer has a radio button group, setting
// this element's checkedness to false.
if ( type_state ( ) = = TypeAttributeState : : RadioButton ) {
2022-12-04 18:02:33 +00:00
DeprecatedString name = this - > name ( ) ;
2022-03-14 23:05:55 +00:00
bool did_reselect_previous_element = false ;
if ( m_legacy_pre_activation_behavior_checked_element_in_group ) {
auto & element_in_group = * m_legacy_pre_activation_behavior_checked_element_in_group ;
if ( name = = element_in_group . name ( ) ) {
element_in_group . set_checked_within_group ( ) ;
did_reselect_previous_element = true ;
}
m_legacy_pre_activation_behavior_checked_element_in_group = nullptr ;
}
if ( ! did_reselect_previous_element )
set_checked ( false , ChangeSource : : User ) ;
}
}
void HTMLInputElement : : legacy_cancelled_activation_behavior_was_not_called ( )
{
m_legacy_pre_activation_behavior_checked_element_in_group = nullptr ;
}
2022-11-05 03:58:14 +00:00
// https://html.spec.whatwg.org/multipage/interaction.html#dom-tabindex
i32 HTMLInputElement : : default_tab_index_value ( ) const
{
// See the base function for the spec comments.
return 0 ;
}
2022-12-30 23:00:11 +00:00
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-setselectionrange
WebIDL : : ExceptionOr < void > HTMLInputElement : : set_selection_range ( u32 start , u32 end , DeprecatedString const & direction )
{
dbgln ( " (STUBBED) HTMLInputElement::set_selection_range(start={}, end={}, direction='{}'). Called on: {} " , start , end , direction , debug_description ( ) ) ;
return { } ;
}
2023-01-28 22:23:16 +00:00
Optional < ARIA : : Role > HTMLInputElement : : default_role ( ) const
2022-11-28 17:58:13 -06:00
{
// https://www.w3.org/TR/html-aria/#el-input-button
if ( type_state ( ) = = TypeAttributeState : : Button )
2023-01-28 22:23:16 +00:00
return ARIA : : Role : : button ;
2022-11-28 17:58:13 -06:00
// https://www.w3.org/TR/html-aria/#el-input-checkbox
if ( type_state ( ) = = TypeAttributeState : : Checkbox )
2023-01-28 22:23:16 +00:00
return ARIA : : Role : : checkbox ;
2022-11-28 17:58:13 -06:00
// https://www.w3.org/TR/html-aria/#el-input-email
if ( type_state ( ) = = TypeAttributeState : : Email & & attribute ( " list " ) . is_null ( ) )
2023-01-28 22:23:16 +00:00
return ARIA : : Role : : textbox ;
2022-11-28 17:58:13 -06:00
// https://www.w3.org/TR/html-aria/#el-input-image
if ( type_state ( ) = = TypeAttributeState : : ImageButton )
2023-01-28 22:23:16 +00:00
return ARIA : : Role : : button ;
2022-11-28 17:58:13 -06:00
// https://www.w3.org/TR/html-aria/#el-input-number
if ( type_state ( ) = = TypeAttributeState : : Number )
2023-01-28 22:23:16 +00:00
return ARIA : : Role : : spinbutton ;
2022-11-28 17:58:13 -06:00
// https://www.w3.org/TR/html-aria/#el-input-radio
if ( type_state ( ) = = TypeAttributeState : : RadioButton )
2023-01-28 22:23:16 +00:00
return ARIA : : Role : : radio ;
2022-11-28 17:58:13 -06:00
// https://www.w3.org/TR/html-aria/#el-input-range
if ( type_state ( ) = = TypeAttributeState : : Range )
2023-01-28 22:23:16 +00:00
return ARIA : : Role : : slider ;
2022-11-28 17:58:13 -06:00
// https://www.w3.org/TR/html-aria/#el-input-reset
if ( type_state ( ) = = TypeAttributeState : : ResetButton )
2023-01-28 22:23:16 +00:00
return ARIA : : Role : : button ;
2022-11-28 17:58:13 -06:00
// https://www.w3.org/TR/html-aria/#el-input-text-list
if ( ( type_state ( ) = = TypeAttributeState : : Text
| | type_state ( ) = = TypeAttributeState : : Search
| | type_state ( ) = = TypeAttributeState : : Telephone
| | type_state ( ) = = TypeAttributeState : : URL
| | type_state ( ) = = TypeAttributeState : : Email )
& & ! attribute ( " list " ) . is_null ( ) )
2023-01-28 22:23:16 +00:00
return ARIA : : Role : : combobox ;
2022-11-28 17:58:13 -06:00
// https://www.w3.org/TR/html-aria/#el-input-search
if ( type_state ( ) = = TypeAttributeState : : Search & & attribute ( " list " ) . is_null ( ) )
2023-01-28 22:23:16 +00:00
return ARIA : : Role : : textbox ;
2022-11-28 17:58:13 -06:00
// https://www.w3.org/TR/html-aria/#el-input-submit
if ( type_state ( ) = = TypeAttributeState : : SubmitButton )
2023-01-28 22:23:16 +00:00
return ARIA : : Role : : button ;
2022-11-28 17:58:13 -06:00
// https://www.w3.org/TR/html-aria/#el-input-tel
if ( type_state ( ) = = TypeAttributeState : : Telephone )
2023-01-28 22:23:16 +00:00
return ARIA : : Role : : textbox ;
2022-11-28 17:58:13 -06:00
// https://www.w3.org/TR/html-aria/#el-input-text
if ( type_state ( ) = = TypeAttributeState : : Text & & attribute ( " list " ) . is_null ( ) )
2023-01-28 22:23:16 +00:00
return ARIA : : Role : : textbox ;
2022-11-28 17:58:13 -06:00
// https://www.w3.org/TR/html-aria/#el-input-url
if ( type_state ( ) = = TypeAttributeState : : URL & & attribute ( " list " ) . is_null ( ) )
2023-01-28 22:23:16 +00:00
return ARIA : : Role : : textbox ;
2022-11-28 17:58:13 -06:00
// https://www.w3.org/TR/html-aria/#el-input-color
// https://www.w3.org/TR/html-aria/#el-input-date
// https://www.w3.org/TR/html-aria/#el-input-datetime-local
// https://www.w3.org/TR/html-aria/#el-input-file
// https://www.w3.org/TR/html-aria/#el-input-hidden
// https://www.w3.org/TR/html-aria/#el-input-month
// https://www.w3.org/TR/html-aria/#el-input-password
// https://www.w3.org/TR/html-aria/#el-input-time
// https://www.w3.org/TR/html-aria/#el-input-week
return { } ;
}
2020-03-07 10:27:02 +01:00
}