Closed Bug 863634 Opened 7 years ago Closed 7 years ago

Update the position of the thumb for <input type=range> when script uses .value, .valueAsNumber, .stepUp() or .stepDown()

Categories

(Core :: DOM: Core & HTML, defect)

defect
Not set

Tracking

()

RESOLVED FIXED
mozilla23

People

(Reporter: surkov, Assigned: jwatt)

References

Details

Attachments

(1 file)

input.value = "4" doesn't change a slider position
Hmm, this used to work, and I thought I had reftests for it. :/ For some reason the invalidation isn't happening.
Assignee: nobody → jwatt
So thing works for ranges with native theming, but not for ranges with -moz-appearance:none.

The reason for this is that when script sets .value, we end up posting a restyle event with nsChangeHint_RepaintFrame under the following call stack:

  nsCSSFrameConstructor::PostRestyleEventCommon
  nsCSSFrameConstructor::PostRestyleEvent
  nsCSSFrameConstructor::ContentStateChanged
  PresShell::ContentStateChanged
  nsDocument::ContentStateChanged
  mozilla::dom::Element::UpdateState
  mozilla::dom::HTMLInputElement::SetValueChanged
  mozilla::dom::HTMLInputElement::SetValueInternal
  mozilla::dom::HTMLInputElement::SetValue
  mozilla::dom::HTMLInputElementBinding::set_value

The nsChangeHint_RepaintFrame comes from nsCSSFrameConstructor::ContentStateChanged where it calls nsNativeThemeCocoa::WidgetStateChanged. Obviously we don't reach that code if the range doesn't have native theming.

Furthermore, the thumb repositioning will only work on OS X, since the position of the thumb _frame_ is never actually updated. The only reason the visual position of the thumb is updated on OS X is because the widget backend for this platform happens to paint the entire range as an atomic unit, without actually using the thumb _frame_. Other widget backends (windows, gtk) do use the thumb frame, so they will be broken regardless of the value of -moz-appearance.
Summary: HTMLInputElement::value doesn't change value of input@type="range" → Update the position of the thumb for <input type=range> when script changes the .value property
Note that this problem doesn't exist for .min/.max, since in HTMLInputElement.h we have code like this:

  void SetMax(const nsAString& aValue, ErrorResult& aRv)
  {
    SetHTMLAttr(nsGkAtoms::max, aValue, aRv);
  }

In other words, setting .min actually sets @min, whereas setting .value does not actually set @value (you need to set .defaultValue to do that).
Note that in addition to .value, .valueAsNumber, .stepUp() and .stepDown() are also broken.
Attached patch patchSplinter Review
Attachment #740003 - Flags: review?(mounir)
Blocks: 841950
No longer depends on: 344618
Comment on attachment 740003 [details] [diff] [review]
patch

Review of attachment 740003 [details] [diff] [review]:
-----------------------------------------------------------------

Why aren't you calling UpdateForValueChange() in ::SetValueInternal() instead? it seems that you call this method a few times just after calling ::SetValueInternal(). Could you have a look and open a follow-up if needed?

r=me with that.

::: layout/reftests/forms/input/range/input-stepDown-unthemed.html
@@ +8,5 @@
> +      document.getElementById('i').stepDown();
> +      document.documentElement.className = '';
> +    }
> +    document.addEventListener("MozReftestInvalidate", setValue);
> +    setTimeout(setValue, 2000); // useful when not running under reftest suite

Could you comment the setTimeout's if they are only for debugging?
Attachment #740003 - Flags: review?(mounir) → review+
https://hg.mozilla.org/integration/mozilla-inbound/rev/18bd842b2897

(In reply to Mounir Lamouri (:mounir) from comment #6)
> Why aren't you calling UpdateForValueChange() in ::SetValueInternal()
> instead? it seems that you call this method a few times just after calling
> ::SetValueInternal(). Could you have a look and open a follow-up if needed?

I did wonder about that but decided against since that would mean that we'd get extra UpdateForValueChange calls under AfterSetAttr for @min/@max/@step, and under SetValue(const nsAString& aValue, ErrorResult& aRv). nsRangeFrame::AttributeChanged already handles updating for @min/@max/@step/@value, and it has a special case that it handles. So I'm not sure that it would be better on balance.

> Could you comment the setTimeout's if they are only for debugging?

They're for running the tests directly, so I left them in. They should be harmless. (We do this as standard in the SVG tests.)
Summary: Update the position of the thumb for <input type=range> when script changes the .value property → Update the position of the thumb for <input type=range> when script uses .value, .valueAsNumber, .stepUp() or .stepDown()
https://hg.mozilla.org/mozilla-central/rev/18bd842b2897
Status: NEW → RESOLVED
Closed: 7 years ago
Flags: in-testsuite+
Resolution: --- → FIXED
Target Milestone: --- → mozilla23
You need to log in before you can comment on or make changes to this bug.