diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 925b7a585e..20030374a8 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -953,10 +953,8 @@ String HTMLInputElement::value_sanitization_algorithm(String const& value) const } } 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. - // 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.bytes_as_string_view().to_double(TrimWhitespace::Yes); - if (!maybe_double.has_value() || !isfinite(maybe_double.value())) + auto maybe_value = parse_floating_point_number(value); + if (!maybe_value.has_value() || !isfinite(maybe_value.value())) return String {}; } else if (type_state() == HTMLInputElement::TypeAttributeState::Date) { // https://html.spec.whatwg.org/multipage/input.html#date-state-(type=date):value-sanitization-algorithm @@ -981,9 +979,16 @@ String HTMLInputElement::value_sanitization_algorithm(String const& value) const return String {}; } 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.bytes_as_string_view().to_double(TrimWhitespace::Yes); - if (!maybe_double.has_value() || !isfinite(maybe_double.value())) - return JS::number_to_string(maybe_double.value_or(0)); + // If the value of the element is not a valid floating-point number, then set it to the best representation, as a floating-point number, of the default value. + auto maybe_value = parse_floating_point_number(value); + if (!maybe_value.has_value() || !isfinite(maybe_value.value())) { + // The default value is the minimum plus half the difference between the minimum and the maximum, unless the maximum is less than the minimum, in which case the default value is the minimum. + auto min = parse_floating_point_number(get_attribute(HTML::AttributeNames::min).value_or("0"_string)).value_or(0); + auto max = parse_floating_point_number(get_attribute(HTML::AttributeNames::max).value_or("1"_string)).value_or(1); + if (max > min) + return JS::number_to_string(min); + return JS::number_to_string(min + (max - min) / 2); + } } 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; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp index caf00f0613..20db16405f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -51,26 +52,21 @@ void HTMLProgressElement::progress_position_updated() document().invalidate_layout(); } +// https://html.spec.whatwg.org/multipage/form-elements.html#dom-progress-value double HTMLProgressElement::value() const { - auto const& value_characters = deprecated_attribute(HTML::AttributeNames::value); - if (value_characters == nullptr) + auto maybe_value_string = get_attribute(HTML::AttributeNames::value); + if (!maybe_value_string.has_value()) return 0; - - // 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_characters.to_double(AK::TrimWhitespace::Yes); - if (!maybe_double.has_value()) + auto maybe_value = parse_floating_point_number(maybe_value_string.value()); + if (!maybe_value.has_value()) return 0; - if (!isfinite(maybe_double.value()) || maybe_double.value() < 0) - return 0; - - return min(maybe_double.value(), max()); + return clamp(maybe_value.value(), 0, max()); } WebIDL::ExceptionOr HTMLProgressElement::set_value(double value) { - if (value < 0) + if (value < 0 || value > max()) return {}; TRY(set_attribute(HTML::AttributeNames::value, MUST(String::number(value)))); @@ -78,21 +74,16 @@ WebIDL::ExceptionOr HTMLProgressElement::set_value(double value) return {}; } +// https://html.spec.whatwg.org/multipage/form-elements.html#dom-progress-max double HTMLProgressElement::max() const { - auto const& max_characters = deprecated_attribute(HTML::AttributeNames::max); - if (max_characters == nullptr) + auto maybe_max_string = get_attribute(HTML::AttributeNames::max); + if (!maybe_max_string.has_value()) return 1; - - // 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 double_or_none = max_characters.to_double(AK::TrimWhitespace::Yes); - if (!double_or_none.has_value()) + auto maybe_max = parse_floating_point_number(maybe_max_string.value()); + if (!maybe_max.has_value()) return 1; - if (!isfinite(double_or_none.value()) || double_or_none.value() <= 0) - return 1; - - return double_or_none.value(); + return AK::max(maybe_max.value(), 0); } WebIDL::ExceptionOr HTMLProgressElement::set_max(double value) diff --git a/Userland/Libraries/LibWeb/HTML/Numbers.cpp b/Userland/Libraries/LibWeb/HTML/Numbers.cpp index 30f8a0a7fe..bbc6a04dbc 100644 --- a/Userland/Libraries/LibWeb/HTML/Numbers.cpp +++ b/Userland/Libraries/LibWeb/HTML/Numbers.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace Web::HTML { @@ -79,4 +80,16 @@ Optional parse_non_negative_integer(StringView string) return static_cast(optional_value.value()); } +// https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-floating-point-number-values +Optional parse_floating_point_number(StringView string) +{ + // FIXME: Implement spec compliant floating point number parsing + auto maybe_double = MUST(String::from_utf8(string)).to_number(TrimWhitespace::Yes); + if (!maybe_double.has_value()) + return {}; + if (!isfinite(maybe_double.value())) + return {}; + return maybe_double.value(); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/Numbers.h b/Userland/Libraries/LibWeb/HTML/Numbers.h index d819f36c13..83f2aeeca4 100644 --- a/Userland/Libraries/LibWeb/HTML/Numbers.h +++ b/Userland/Libraries/LibWeb/HTML/Numbers.h @@ -15,4 +15,6 @@ Optional parse_integer(StringView string); Optional parse_non_negative_integer(StringView string); +Optional parse_floating_point_number(StringView string); + } diff --git a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp index a0ac8d68ef..1c9605ec08 100644 --- a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp +++ b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp @@ -402,8 +402,7 @@ ErrorOr TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder:: bar_style->set_property(CSS::PropertyID::Display, CSS::DisplayStyleValue::create(CSS::Display::from_short(CSS::Display::Short::FlowRoot))); auto value_style = TRY(style_computer.compute_style(progress, CSS::Selector::PseudoElement::ProgressValue)); value_style->set_property(CSS::PropertyID::Display, CSS::DisplayStyleValue::create(CSS::Display::from_short(CSS::Display::Short::Block))); - auto position = progress.position(); - value_style->set_property(CSS::PropertyID::Width, CSS::PercentageStyleValue::create(CSS::Percentage(position >= 0 ? round_to(100 * position) : 0))); + value_style->set_property(CSS::PropertyID::Width, CSS::PercentageStyleValue::create(CSS::Percentage(progress.position() * 100))); auto bar_display = bar_style->display(); auto value_display = value_style->display(); auto progress_bar = DOM::Element::create_layout_node_for_display_type(document, bar_display, bar_style, nullptr);