mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:52:45 +00:00 
			
		
		
		
	LibWeb: Add input and textarea minlength and maxlength support
This commit is contained in:
		
							parent
							
								
									9b645d20b9
								
							
						
					
					
						commit
						a2f101c10b
					
				
					 15 changed files with 162 additions and 5 deletions
				
			
		
							
								
								
									
										1
									
								
								Tests/LibWeb/Text/expected/input-maxlength.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								Tests/LibWeb/Text/expected/input-maxlength.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | Hello  | ||||||
							
								
								
									
										1
									
								
								Tests/LibWeb/Text/expected/textarea-maxlength.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								Tests/LibWeb/Text/expected/textarea-maxlength.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | Hello  | ||||||
							
								
								
									
										7
									
								
								Tests/LibWeb/Text/input/input-maxlength.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Tests/LibWeb/Text/input/input-maxlength.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | <input id="input" type="text" maxlength="5"><script src="include.js"></script><script> | ||||||
|  |     test(() => { | ||||||
|  |         const input = document.getElementById('input'); | ||||||
|  |         internals.sendText(input, 'Hello World!'); | ||||||
|  |         internals.commitText(); | ||||||
|  |     }); | ||||||
|  | </script> | ||||||
							
								
								
									
										7
									
								
								Tests/LibWeb/Text/input/textarea-maxlength.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Tests/LibWeb/Text/input/textarea-maxlength.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | <textarea id="textarea" maxlength="5"></textarea><script src="include.js"></script><script> | ||||||
|  |     test(() => { | ||||||
|  |         const textarea = document.getElementById('textarea'); | ||||||
|  |         internals.sendText(textarea, 'Hello World!'); | ||||||
|  |         internals.commitText(); | ||||||
|  |     }); | ||||||
|  | </script> | ||||||
|  | @ -35,6 +35,9 @@ public: | ||||||
| 
 | 
 | ||||||
|     void set_always_editable(bool b) { m_always_editable = b; } |     void set_always_editable(bool b) { m_always_editable = b; } | ||||||
| 
 | 
 | ||||||
|  |     Optional<size_t> max_length() const { return m_max_length; } | ||||||
|  |     void set_max_length(Optional<size_t> max_length) { m_max_length = move(max_length); } | ||||||
|  | 
 | ||||||
|     template<DerivedFrom<EditableTextNodeOwner> T> |     template<DerivedFrom<EditableTextNodeOwner> T> | ||||||
|     void set_editable_text_node_owner(Badge<T>, EditableTextNodeOwner& owner_element) { m_owner = &owner_element; } |     void set_editable_text_node_owner(Badge<T>, EditableTextNodeOwner& owner_element) { m_owner = &owner_element; } | ||||||
|     EditableTextNodeOwner* editable_text_node_owner() { return m_owner.ptr(); } |     EditableTextNodeOwner* editable_text_node_owner() { return m_owner.ptr(); } | ||||||
|  | @ -55,6 +58,7 @@ private: | ||||||
|     JS::GCPtr<EditableTextNodeOwner> m_owner; |     JS::GCPtr<EditableTextNodeOwner> m_owner; | ||||||
| 
 | 
 | ||||||
|     bool m_always_editable { false }; |     bool m_always_editable { false }; | ||||||
|  |     Optional<size_t> m_max_length {}; | ||||||
|     bool m_is_password_input { false }; |     bool m_is_password_input { false }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -103,9 +103,11 @@ namespace AttributeNames { | ||||||
|     __ENUMERATE_HTML_ATTRIBUTE(marginheight)               \ |     __ENUMERATE_HTML_ATTRIBUTE(marginheight)               \ | ||||||
|     __ENUMERATE_HTML_ATTRIBUTE(marginwidth)                \ |     __ENUMERATE_HTML_ATTRIBUTE(marginwidth)                \ | ||||||
|     __ENUMERATE_HTML_ATTRIBUTE(max)                        \ |     __ENUMERATE_HTML_ATTRIBUTE(max)                        \ | ||||||
|  |     __ENUMERATE_HTML_ATTRIBUTE(maxlength)                  \ | ||||||
|     __ENUMERATE_HTML_ATTRIBUTE(media)                      \ |     __ENUMERATE_HTML_ATTRIBUTE(media)                      \ | ||||||
|     __ENUMERATE_HTML_ATTRIBUTE(method)                     \ |     __ENUMERATE_HTML_ATTRIBUTE(method)                     \ | ||||||
|     __ENUMERATE_HTML_ATTRIBUTE(min)                        \ |     __ENUMERATE_HTML_ATTRIBUTE(min)                        \ | ||||||
|  |     __ENUMERATE_HTML_ATTRIBUTE(minlength)                  \ | ||||||
|     __ENUMERATE_HTML_ATTRIBUTE(multiple)                   \ |     __ENUMERATE_HTML_ATTRIBUTE(multiple)                   \ | ||||||
|     __ENUMERATE_HTML_ATTRIBUTE(muted)                      \ |     __ENUMERATE_HTML_ATTRIBUTE(muted)                      \ | ||||||
|     __ENUMERATE_HTML_ATTRIBUTE(name)                       \ |     __ENUMERATE_HTML_ATTRIBUTE(name)                       \ | ||||||
|  |  | ||||||
|  | @ -578,6 +578,19 @@ static bool is_allowed_to_be_readonly(HTML::HTMLInputElement::TypeAttributeState | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // https://html.spec.whatwg.org/multipage/input.html#attr-input-maxlength
 | ||||||
|  | void HTMLInputElement::handle_maxlength_attribute() | ||||||
|  | { | ||||||
|  |     if (m_text_node) { | ||||||
|  |         auto max_length = this->max_length(); | ||||||
|  |         if (max_length >= 0) { | ||||||
|  |             m_text_node->set_max_length(max_length); | ||||||
|  |         } else { | ||||||
|  |             m_text_node->set_max_length({}); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // https://html.spec.whatwg.org/multipage/input.html#attr-input-readonly
 | // https://html.spec.whatwg.org/multipage/input.html#attr-input-readonly
 | ||||||
| void HTMLInputElement::handle_readonly_attribute(Optional<String> const& maybe_value) | void HTMLInputElement::handle_readonly_attribute(Optional<String> const& maybe_value) | ||||||
| { | { | ||||||
|  | @ -728,6 +741,7 @@ void HTMLInputElement::create_text_input_shadow_tree() | ||||||
|     m_text_node->set_editable_text_node_owner(Badge<HTMLInputElement> {}, *this); |     m_text_node->set_editable_text_node_owner(Badge<HTMLInputElement> {}, *this); | ||||||
|     if (type_state() == TypeAttributeState::Password) |     if (type_state() == TypeAttributeState::Password) | ||||||
|         m_text_node->set_is_password_input({}, true); |         m_text_node->set_is_password_input({}, true); | ||||||
|  |     handle_maxlength_attribute(); | ||||||
|     MUST(m_inner_text_element->append_child(*m_text_node)); |     MUST(m_inner_text_element->append_child(*m_text_node)); | ||||||
| 
 | 
 | ||||||
|     update_placeholder_visibility(); |     update_placeholder_visibility(); | ||||||
|  | @ -1024,6 +1038,8 @@ void HTMLInputElement::form_associated_element_attribute_changed(FlyString const | ||||||
|     } else if (name == HTML::AttributeNames::alt) { |     } else if (name == HTML::AttributeNames::alt) { | ||||||
|         if (layout_node() && type_state() == TypeAttributeState::ImageButton) |         if (layout_node() && type_state() == TypeAttributeState::ImageButton) | ||||||
|             did_update_alt_text(verify_cast<Layout::ImageBox>(*layout_node())); |             did_update_alt_text(verify_cast<Layout::ImageBox>(*layout_node())); | ||||||
|  |     } else if (name == HTML::AttributeNames::maxlength) { | ||||||
|  |         handle_maxlength_attribute(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1445,6 +1461,40 @@ void HTMLInputElement::apply_presentational_hints(CSS::StyleProperties& style) c | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | //  https://html.spec.whatwg.org/multipage/input.html#dom-input-maxlength
 | ||||||
|  | WebIDL::Long HTMLInputElement::max_length() const | ||||||
|  | { | ||||||
|  |     // The maxLength IDL attribute must reflect the maxlength content attribute, limited to only non-negative numbers.
 | ||||||
|  |     if (auto maxlength_string = get_attribute(HTML::AttributeNames::maxlength); maxlength_string.has_value()) { | ||||||
|  |         if (auto maxlength = parse_non_negative_integer(*maxlength_string); maxlength.has_value()) | ||||||
|  |             return *maxlength; | ||||||
|  |     } | ||||||
|  |     return -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | WebIDL::ExceptionOr<void> HTMLInputElement::set_max_length(WebIDL::Long value) | ||||||
|  | { | ||||||
|  |     // The maxLength IDL attribute must reflect the maxlength content attribute, limited to only non-negative numbers.
 | ||||||
|  |     return set_attribute(HTML::AttributeNames::maxlength, TRY(convert_non_negative_integer_to_string(realm(), value))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // https://html.spec.whatwg.org/multipage/input.html#dom-input-minlength
 | ||||||
|  | WebIDL::Long HTMLInputElement::min_length() const | ||||||
|  | { | ||||||
|  |     // The minLength IDL attribute must reflect the minlength content attribute, limited to only non-negative numbers.
 | ||||||
|  |     if (auto minlength_string = get_attribute(HTML::AttributeNames::minlength); minlength_string.has_value()) { | ||||||
|  |         if (auto minlength = parse_non_negative_integer(*minlength_string); minlength.has_value()) | ||||||
|  |             return *minlength; | ||||||
|  |     } | ||||||
|  |     return -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | WebIDL::ExceptionOr<void> HTMLInputElement::set_min_length(WebIDL::Long value) | ||||||
|  | { | ||||||
|  |     // The minLength IDL attribute must reflect the minlength content attribute, limited to only non-negative numbers.
 | ||||||
|  |     return set_attribute(HTML::AttributeNames::minlength, TRY(convert_non_negative_integer_to_string(realm(), value))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // https://html.spec.whatwg.org/multipage/input.html#the-size-attribute
 | // https://html.spec.whatwg.org/multipage/input.html#the-size-attribute
 | ||||||
| unsigned HTMLInputElement::size() const | unsigned HTMLInputElement::size() const | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -16,6 +16,7 @@ | ||||||
| #include <LibWeb/HTML/HTMLElement.h> | #include <LibWeb/HTML/HTMLElement.h> | ||||||
| #include <LibWeb/Layout/ImageProvider.h> | #include <LibWeb/Layout/ImageProvider.h> | ||||||
| #include <LibWeb/WebIDL/DOMException.h> | #include <LibWeb/WebIDL/DOMException.h> | ||||||
|  | #include <LibWeb/WebIDL/Types.h> | ||||||
| 
 | 
 | ||||||
| namespace Web::HTML { | namespace Web::HTML { | ||||||
| 
 | 
 | ||||||
|  | @ -104,6 +105,12 @@ public: | ||||||
|     // https://html.spec.whatwg.org/multipage/input.html#update-the-file-selection
 |     // https://html.spec.whatwg.org/multipage/input.html#update-the-file-selection
 | ||||||
|     void update_the_file_selection(JS::NonnullGCPtr<FileAPI::FileList>); |     void update_the_file_selection(JS::NonnullGCPtr<FileAPI::FileList>); | ||||||
| 
 | 
 | ||||||
|  |     WebIDL::Long max_length() const; | ||||||
|  |     WebIDL::ExceptionOr<void> set_max_length(WebIDL::Long); | ||||||
|  | 
 | ||||||
|  |     WebIDL::Long min_length() const; | ||||||
|  |     WebIDL::ExceptionOr<void> set_min_length(WebIDL::Long); | ||||||
|  | 
 | ||||||
|     unsigned size() const; |     unsigned size() const; | ||||||
|     WebIDL::ExceptionOr<void> set_size(unsigned value); |     WebIDL::ExceptionOr<void> set_size(unsigned value); | ||||||
| 
 | 
 | ||||||
|  | @ -235,6 +242,7 @@ private: | ||||||
|     WebIDL::ExceptionOr<void> run_input_activation_behavior(DOM::Event const&); |     WebIDL::ExceptionOr<void> run_input_activation_behavior(DOM::Event const&); | ||||||
|     void set_checked_within_group(); |     void set_checked_within_group(); | ||||||
| 
 | 
 | ||||||
|  |     void handle_maxlength_attribute(); | ||||||
|     void handle_readonly_attribute(Optional<String> const& value); |     void handle_readonly_attribute(Optional<String> const& value); | ||||||
|     WebIDL::ExceptionOr<void> handle_src_attribute(StringView value); |     WebIDL::ExceptionOr<void> handle_src_attribute(StringView value); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -25,9 +25,9 @@ interface HTMLInputElement : HTMLElement { | ||||||
|     attribute boolean indeterminate; |     attribute boolean indeterminate; | ||||||
|     // FIXME: readonly attribute HTMLDataListElement? list; |     // FIXME: readonly attribute HTMLDataListElement? list; | ||||||
|     [CEReactions, Reflect] attribute DOMString max; |     [CEReactions, Reflect] attribute DOMString max; | ||||||
|     // FIXME: [CEReactions] attribute long maxLength; |     [CEReactions] attribute long maxLength; | ||||||
|     [CEReactions, Reflect] attribute DOMString min; |     [CEReactions, Reflect] attribute DOMString min; | ||||||
|     // FIXME: [CEReactions] attribute long minLength; |     [CEReactions] attribute long minLength; | ||||||
|     [CEReactions, Reflect] attribute boolean multiple; |     [CEReactions, Reflect] attribute boolean multiple; | ||||||
|     [CEReactions, Reflect] attribute DOMString name; |     [CEReactions, Reflect] attribute DOMString name; | ||||||
|     // FIXME: [CEReactions] attribute DOMString pattern; |     // FIXME: [CEReactions] attribute DOMString pattern; | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2020, the SerenityOS developers. |  * Copyright (c) 2020, the SerenityOS developers. | ||||||
|  * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org> |  * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org> | ||||||
|  |  * Copyright (c) 2024, Bastiaan van der Plaat <bastiaan.v.d.plaat@gmail.com> | ||||||
|  * |  * | ||||||
|  * SPDX-License-Identifier: BSD-2-Clause |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
|  | @ -147,6 +148,40 @@ u32 HTMLTextAreaElement::text_length() const | ||||||
|     return Utf16View { utf16_data }.length_in_code_units(); |     return Utf16View { utf16_data }.length_in_code_units(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // https://html.spec.whatwg.org/multipage/form-elements.html#dom-textarea-maxlength
 | ||||||
|  | WebIDL::Long HTMLTextAreaElement::max_length() const | ||||||
|  | { | ||||||
|  |     // The maxLength IDL attribute must reflect the maxlength content attribute, limited to only non-negative numbers.
 | ||||||
|  |     if (auto maxlength_string = get_attribute(HTML::AttributeNames::maxlength); maxlength_string.has_value()) { | ||||||
|  |         if (auto maxlength = parse_non_negative_integer(*maxlength_string); maxlength.has_value()) | ||||||
|  |             return *maxlength; | ||||||
|  |     } | ||||||
|  |     return -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | WebIDL::ExceptionOr<void> HTMLTextAreaElement::set_max_length(WebIDL::Long value) | ||||||
|  | { | ||||||
|  |     // The maxLength IDL attribute must reflect the maxlength content attribute, limited to only non-negative numbers.
 | ||||||
|  |     return set_attribute(HTML::AttributeNames::maxlength, TRY(convert_non_negative_integer_to_string(realm(), value))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // https://html.spec.whatwg.org/multipage/form-elements.html#dom-textarea-minlength
 | ||||||
|  | WebIDL::Long HTMLTextAreaElement::min_length() const | ||||||
|  | { | ||||||
|  |     // The minLength IDL attribute must reflect the minlength content attribute, limited to only non-negative numbers.
 | ||||||
|  |     if (auto minlength_string = get_attribute(HTML::AttributeNames::minlength); minlength_string.has_value()) { | ||||||
|  |         if (auto minlength = parse_non_negative_integer(*minlength_string); minlength.has_value()) | ||||||
|  |             return *minlength; | ||||||
|  |     } | ||||||
|  |     return -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | WebIDL::ExceptionOr<void> HTMLTextAreaElement::set_min_length(WebIDL::Long value) | ||||||
|  | { | ||||||
|  |     // The minLength IDL attribute must reflect the minlength content attribute, limited to only non-negative numbers.
 | ||||||
|  |     return set_attribute(HTML::AttributeNames::minlength, TRY(convert_non_negative_integer_to_string(realm(), value))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // https://html.spec.whatwg.org/multipage/form-elements.html#dom-textarea-cols
 | // https://html.spec.whatwg.org/multipage/form-elements.html#dom-textarea-cols
 | ||||||
| unsigned HTMLTextAreaElement::cols() const | unsigned HTMLTextAreaElement::cols() const | ||||||
| { | { | ||||||
|  | @ -208,6 +243,7 @@ void HTMLTextAreaElement::create_shadow_tree_if_needed() | ||||||
|     // NOTE: If `children_changed()` was called before now, `m_raw_value` will hold the text content.
 |     // NOTE: If `children_changed()` was called before now, `m_raw_value` will hold the text content.
 | ||||||
|     //       Otherwise, it will get filled in whenever that does get called.
 |     //       Otherwise, it will get filled in whenever that does get called.
 | ||||||
|     m_text_node->set_text_content(m_raw_value); |     m_text_node->set_text_content(m_raw_value); | ||||||
|  |     handle_maxlength_attribute(); | ||||||
|     MUST(m_inner_text_element->append_child(*m_text_node)); |     MUST(m_inner_text_element->append_child(*m_text_node)); | ||||||
| 
 | 
 | ||||||
|     update_placeholder_visibility(); |     update_placeholder_visibility(); | ||||||
|  | @ -223,6 +259,19 @@ void HTMLTextAreaElement::handle_readonly_attribute(Optional<String> const& mayb | ||||||
|         m_text_node->set_always_editable(m_is_mutable); |         m_text_node->set_always_editable(m_is_mutable); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // https://html.spec.whatwg.org/multipage/form-elements.html#dom-textarea-maxlength
 | ||||||
|  | void HTMLTextAreaElement::handle_maxlength_attribute() | ||||||
|  | { | ||||||
|  |     if (m_text_node) { | ||||||
|  |         auto max_length = this->max_length(); | ||||||
|  |         if (max_length >= 0) { | ||||||
|  |             m_text_node->set_max_length(max_length); | ||||||
|  |         } else { | ||||||
|  |             m_text_node->set_max_length({}); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void HTMLTextAreaElement::update_placeholder_visibility() | void HTMLTextAreaElement::update_placeholder_visibility() | ||||||
| { | { | ||||||
|     if (!m_placeholder_element) |     if (!m_placeholder_element) | ||||||
|  | @ -257,6 +306,8 @@ void HTMLTextAreaElement::form_associated_element_attribute_changed(FlyString co | ||||||
|             m_placeholder_text_node->set_data(value.value_or(String {})); |             m_placeholder_text_node->set_data(value.value_or(String {})); | ||||||
|     } else if (name == HTML::AttributeNames::readonly) { |     } else if (name == HTML::AttributeNames::readonly) { | ||||||
|         handle_readonly_attribute(value); |         handle_readonly_attribute(value); | ||||||
|  |     } else if (name == HTML::AttributeNames::maxlength) { | ||||||
|  |         handle_maxlength_attribute(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2020, the SerenityOS developers. |  * Copyright (c) 2020, the SerenityOS developers. | ||||||
|  * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org> |  * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org> | ||||||
|  |  * Copyright (c) 2024, Bastiaan van der Plaat <bastiaan.v.d.plaat@gmail.com> | ||||||
|  * |  * | ||||||
|  * SPDX-License-Identifier: BSD-2-Clause |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
|  | @ -11,6 +12,7 @@ | ||||||
| #include <LibWeb/DOM/Text.h> | #include <LibWeb/DOM/Text.h> | ||||||
| #include <LibWeb/HTML/FormAssociatedElement.h> | #include <LibWeb/HTML/FormAssociatedElement.h> | ||||||
| #include <LibWeb/HTML/HTMLElement.h> | #include <LibWeb/HTML/HTMLElement.h> | ||||||
|  | #include <LibWeb/WebIDL/Types.h> | ||||||
| 
 | 
 | ||||||
| namespace Web::HTML { | namespace Web::HTML { | ||||||
| 
 | 
 | ||||||
|  | @ -77,6 +79,12 @@ public: | ||||||
| 
 | 
 | ||||||
|     u32 text_length() const; |     u32 text_length() const; | ||||||
| 
 | 
 | ||||||
|  |     WebIDL::Long max_length() const; | ||||||
|  |     WebIDL::ExceptionOr<void> set_max_length(WebIDL::Long); | ||||||
|  | 
 | ||||||
|  |     WebIDL::Long min_length() const; | ||||||
|  |     WebIDL::ExceptionOr<void> set_min_length(WebIDL::Long); | ||||||
|  | 
 | ||||||
|     unsigned cols() const; |     unsigned cols() const; | ||||||
|     WebIDL::ExceptionOr<void> set_cols(unsigned); |     WebIDL::ExceptionOr<void> set_cols(unsigned); | ||||||
| 
 | 
 | ||||||
|  | @ -95,6 +103,7 @@ private: | ||||||
|     void create_shadow_tree_if_needed(); |     void create_shadow_tree_if_needed(); | ||||||
| 
 | 
 | ||||||
|     void handle_readonly_attribute(Optional<String> const& value); |     void handle_readonly_attribute(Optional<String> const& value); | ||||||
|  |     void handle_maxlength_attribute(); | ||||||
| 
 | 
 | ||||||
|     void update_placeholder_visibility(); |     void update_placeholder_visibility(); | ||||||
|     JS::GCPtr<DOM::Element> m_placeholder_element; |     JS::GCPtr<DOM::Element> m_placeholder_element; | ||||||
|  |  | ||||||
|  | @ -11,8 +11,8 @@ interface HTMLTextAreaElement : HTMLElement { | ||||||
|     [CEReactions, Reflect=dirname] attribute DOMString dirName; |     [CEReactions, Reflect=dirname] attribute DOMString dirName; | ||||||
|     [CEReactions, Reflect] attribute boolean disabled; |     [CEReactions, Reflect] attribute boolean disabled; | ||||||
|     readonly attribute HTMLFormElement? form; |     readonly attribute HTMLFormElement? form; | ||||||
|     // FIXME: [CEReactions] attribute long maxLength; |     [CEReactions] attribute long maxLength; | ||||||
|     // FIXME: [CEReactions] attribute long minLength; |     [CEReactions] attribute long minLength; | ||||||
|     [CEReactions, Reflect] attribute DOMString name; |     [CEReactions, Reflect] attribute DOMString name; | ||||||
|     [CEReactions, Reflect] attribute DOMString placeholder; |     [CEReactions, Reflect] attribute DOMString placeholder; | ||||||
|     [CEReactions, Reflect=readonly] attribute boolean readOnly; |     [CEReactions, Reflect=readonly] attribute boolean readOnly; | ||||||
|  |  | ||||||
|  | @ -92,4 +92,11 @@ Optional<double> parse_floating_point_number(StringView string) | ||||||
|     return maybe_double.value(); |     return maybe_double.value(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | WebIDL::ExceptionOr<String> convert_non_negative_integer_to_string(JS::Realm& realm, WebIDL::Long value) | ||||||
|  | { | ||||||
|  |     if (value < 0) | ||||||
|  |         return WebIDL::IndexSizeError::create(realm, "The attribute is limited to only non-negative numbers"_fly_string); | ||||||
|  |     return MUST(String::number(value)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,6 +8,8 @@ | ||||||
| 
 | 
 | ||||||
| #include <AK/Forward.h> | #include <AK/Forward.h> | ||||||
| #include <AK/String.h> | #include <AK/String.h> | ||||||
|  | #include <LibWeb/WebIDL/ExceptionOr.h> | ||||||
|  | #include <LibWeb/WebIDL/Types.h> | ||||||
| 
 | 
 | ||||||
| namespace Web::HTML { | namespace Web::HTML { | ||||||
| 
 | 
 | ||||||
|  | @ -17,4 +19,6 @@ Optional<u32> parse_non_negative_integer(StringView string); | ||||||
| 
 | 
 | ||||||
| Optional<double> parse_floating_point_number(StringView string); | Optional<double> parse_floating_point_number(StringView string); | ||||||
| 
 | 
 | ||||||
|  | WebIDL::ExceptionOr<String> convert_non_negative_integer_to_string(JS::Realm&, WebIDL::Long); | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -111,8 +111,14 @@ void EditEventHandler::handle_insert(JS::NonnullGCPtr<DOM::Position> position, u | ||||||
|         builder.append(node.data().bytes_as_string_view().substring_view(0, position->offset())); |         builder.append(node.data().bytes_as_string_view().substring_view(0, position->offset())); | ||||||
|         builder.append_code_point(code_point); |         builder.append_code_point(code_point); | ||||||
|         builder.append(node.data().bytes_as_string_view().substring_view(position->offset())); |         builder.append(node.data().bytes_as_string_view().substring_view(position->offset())); | ||||||
|         node.set_data(MUST(builder.to_string())); |  | ||||||
| 
 | 
 | ||||||
|  |         // Cut string by max length
 | ||||||
|  |         // FIXME: Cut by UTF-16 code units instead of raw bytes
 | ||||||
|  |         if (auto max_length = node.max_length(); max_length.has_value() && builder.string_view().length() > *max_length) { | ||||||
|  |             node.set_data(MUST(String::from_utf8(builder.string_view().substring_view(0, *max_length)))); | ||||||
|  |         } else { | ||||||
|  |             node.set_data(MUST(builder.to_string())); | ||||||
|  |         } | ||||||
|         node.invalidate_style(); |         node.invalidate_style(); | ||||||
|     } else { |     } else { | ||||||
|         auto& node = *position->node(); |         auto& node = *position->node(); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Bastiaan van der Plaat
						Bastiaan van der Plaat