Closed
Bug 851090
Opened 12 years ago
Closed 12 years ago
Make <input type=range> fire "change"/"input" events as appropriate
Categories
(Core :: DOM: Core & HTML, defect)
Core
DOM: Core & HTML
Tracking
()
RESOLVED
FIXED
mozilla22
People
(Reporter: jwatt, Assigned: jwatt)
References
Details
(Keywords: dev-doc-needed)
Attachments
(1 file, 3 obsolete files)
(deleted),
patch
|
mounir
:
review+
|
Details | Diff | Splinter Review |
I just noticed that <input type=range> is not currently firing "change"/"input" events. That needs to be fixed for release.
Assignee | ||
Comment 1•12 years ago
|
||
Attachment #724922 -
Flags: feedback?(mounir)
Assignee | ||
Updated•12 years ago
|
Attachment #724922 -
Flags: feedback?(mounir) → review?
Assignee | ||
Updated•12 years ago
|
Attachment #724922 -
Flags: review? → review?(mounir)
Assignee | ||
Comment 2•12 years ago
|
||
Actually we can't just assert that nsContentUtils::IsCallerChrome(), since there is one rare case where that will fail (see the comment I added).
Attachment #724922 -
Attachment is obsolete: true
Attachment #724922 -
Flags: review?(mounir)
Attachment #724929 -
Flags: review?(mounir)
Comment 3•12 years ago
|
||
Comment on attachment 724929 [details] [diff] [review]
patch
Review of attachment 724929 [details] [diff] [review]:
-----------------------------------------------------------------
You do not seem to update the code in ::HandleTypeChange(), ::SetValue(), ::PostHandleEvent(), ::PreHandleEvent().
Basically, look at all FireChangeIfNeeded() calls and mFocusedValue calls.
::: content/html/content/src/nsHTMLInputElement.cpp
@@ +2608,5 @@
> + if (!nsContentUtils::IsCallerChrome()) {
> + // This can happen when script does input.type=non-range during a thumb
> + // drag, causing CancelRangeThumbDrag() to call us.
> + return;
> + }
I am not really sure I do understand what is happening here. I shall have a deeper look.
Attachment #724929 -
Flags: review?(mounir) → review-
Assignee | ||
Comment 4•12 years ago
|
||
Why do I need to look at the places that reference mFocusedValue?
(In reply to Mounir Lamouri (:mounir) from comment #3)
> You do not seem to update the code in ::HandleTypeChange()
There isn't any FireChangeEventIfNeeded() call there.
> ::SetValue(),
or here
> ::PostHandleEvent(),
This calls SetValueOfRangeForUserEvent, and I've added a FireChangeEventIfNeeded() call to that method.
> ::PreHandleEvent().
The call there should work fine for range as-is, no? Or do you want me to add a check for range with the IsExperimentalMobileType() check?
> I am not really sure I do understand what is happening here. I shall have a
> deeper look.
If you have it assert instead of return, test_input_range_mouse_and_touch_events.html will trigger the assert.
Assignee | ||
Comment 5•12 years ago
|
||
(In reply to Jonathan Watt [:jwatt] from comment #4)
> Why do I need to look at the places that reference mFocusedValue?
Ah, okay, I understand; we sometimes set mFocusedValue to the current value to deliberately prevent the change event from being dispatched.
The following comments still stand:
> > ::PostHandleEvent(),
>
> This calls SetValueOfRangeForUserEvent, and I've added a
> FireChangeEventIfNeeded() call to that method.
>
> > ::PreHandleEvent().
>
> The call there should work fine for range as-is, no? Or do you want me to
> add a check for range with the IsExperimentalMobileType() check?
>
> > I am not really sure I do understand what is happening here. I shall have a
> > deeper look.
>
> If you have it assert instead of return,
> test_input_range_mouse_and_touch_events.html will trigger the assert.
Or to give you the stack when script does type=range -> type=something-else:
nsHTMLInputElement::SetValueOfRangeForUserEvent
nsHTMLInputElement::CancelRangeThumbDrag
nsHTMLInputElement::HandleTypeChange
nsHTMLInputElement::ParseAttribute
mozilla::dom::Element::SetAttr
nsGenericHTMLElement::SetAttr
nsGenericHTMLElement::SetAttr
nsGenericHTMLElement::SetAttrHelper
nsHTMLInputElement::SetType
nsIDOMHTMLInputElement_SetType
Attachment #724929 -
Attachment is obsolete: true
Attachment #725213 -
Flags: review?(mounir)
Comment 6•12 years ago
|
||
Comment on attachment 725213 [details] [diff] [review]
patch
Review of attachment 725213 [details] [diff] [review]:
-----------------------------------------------------------------
So, I think we should change an input event whenever the value is changed but we shouldn't follow the behaviour of Webkit and IE10 regarding the change event. I think firing a change event when we blur is the way to go. We could also fire a change event when a drag is finished given that it can be considered somehow as a 'commit' [1].
Regarding the tests, I guess you could add some specific tests in test_change_event.html for the <input type='range'>. You would have to handle the blur and drag scenarios. Do we have tests for the input events?
I think you could do a helper method like:
bool DoesFireChangeOnBlur() const {
return IsSingleLineTextControl(false) || mType == NS_FORM_INPUT_RANGE;
}
[1] http://www.whatwg.org/specs/web-apps/current-work/multipage/common-input-element-attributes.html#event-input-change
::: content/html/content/src/nsHTMLInputElement.cpp
@@ +2605,5 @@
> frame->UpdateThumbPositionForValueChange();
> }
> + if (!nsContentUtils::IsCallerChrome()) {
> + // This can happen when script does input.type=non-range during a thumb
> + // drag, causing CancelRangeThumbDrag() to call us.
So, I think we shouldn't do that here. IsCallerChrome() works in most situations but wouldn't work if the type change is made by a chrome privileged caller like Firefox UI.
I would prefer to not handle this edge case here and open a follow-up (blocking the feature shipping) to fix it properly.
@@ +2612,5 @@
> + nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
> + static_cast<nsIDOMHTMLInputElement*>(this),
> + NS_LITERAL_STRING("input"), true,
> + true);
> + FireChangeEventIfNeeded();
I guess that would have to be done elsewhere (like FinishRangeThumbDrag()).
@@ +3316,5 @@
> // Updating mFocusedValue in consequence:
> // If the new type is a single line text control but the previous wasn't, we
> // should set mFocusedValue to the current value.
> // Otherwise, if the new type isn't a text control but the previous was, we
> // should clear out mFocusedValue.
Can you update the comment?
::: content/html/content/test/forms/test_change_event.html
@@ +155,5 @@
> else {
> input = document.getElementById("input_" + NonTextInputTypes[i]);
> input.focus();
> + if (input.type == "range") {
> + synthesizeKey("VK_HOME", {});
I think we should not fire change event in that case but only when we blur the element after changing its value with the keyboard.
Attachment #725213 -
Flags: review?(mounir) → review-
Assignee | ||
Comment 7•12 years ago
|
||
(In reply to Mounir Lamouri (:mounir) from comment #6)
> So, I think we should change an input event whenever the value is changed
> but we shouldn't follow the behaviour of Webkit and IE10 regarding the
> change event.
Okay, but, as noted on IRC, we'll not work with the demos that I've seen. We can try "fixing the web though". :)
> Regarding the tests, I guess you could add some specific tests in
> test_change_event.html for the <input type='range'>. You would have to
> handle the blur and drag scenarios. Do we have tests for the input events?
I added "input" events too, although I don't see any such tests for other input types.
Attachment #725213 -
Attachment is obsolete: true
Attachment #725531 -
Flags: review?(mounir)
Comment 8•12 years ago
|
||
Comment on attachment 725531 [details] [diff] [review]
patch
Review of attachment 725531 [details] [diff] [review]:
-----------------------------------------------------------------
r=me with the comments applied an the follow-up filed.
Also, I would have preferred to not test the input event behaviour in test_change_event.html. It would be great if you could create a test_input_event.html test. Otherwise, at least file a follow-up for that to be done.
::: content/html/content/src/nsHTMLInputElement.cpp
@@ +2606,5 @@
> }
> + nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
> + static_cast<nsIDOMHTMLInputElement*>(this),
> + NS_LITERAL_STRING("input"), true,
> + true);
The event should not be cancellable per HTML spec. Make the second boolean 'false'.
@@ +3310,5 @@
> // Updating mFocusedValue in consequence:
> + // If the new type is a single line text control or range, but the previous
> + // wasn't, we should set mFocusedValue to the current value.
> + // Otherwise, if the new type isn't a text control or range, but the previous
> + // was, we should clear out mFocusedValue.
I would not say "single line text control or range" but "firing change event on blur" just so we hide the implementation of the method.
::: content/html/content/src/nsHTMLInputElement.h
@@ +819,5 @@
> bool mIsDraggingRange : 1;
>
> private:
> +
> + bool DoesFireChangeOnBlur(uint8_t aType) const {
Make it static.
@@ +826,5 @@
> + }
> +
> + bool DoesFireChangeOnBlur() const {
> + return IsSingleLineTextControl(false, mType) ||
> + mType == NS_FORM_INPUT_RANGE;
return DoesFireChangeOnBlur(mType);
Attachment #725531 -
Flags: review?(mounir) → review+
Assignee | ||
Comment 9•12 years ago
|
||
https://hg.mozilla.org/integration/mozilla-inbound/rev/46585b03426a
(In reply to Mounir Lamouri (:mounir) from comment #8)
> Also, I would have preferred to not test the input event behaviour in
> test_change_event.html. It would be great if you could create a
> test_input_event.html test. Otherwise, at least file a follow-up for that to
> be done.
I'll file a follow-up, since I'd like to land this but don't for now have time to create a separate test that will cover all the things you can dream up for a standalone test and meet your exacting standards. ;) I also think it probably makes sense to rename the test to test_change_and_input_events.html and integrate "input" events for all types there, but don't want to hold things up as we discuss that.
> @@ +826,5 @@
> > + }
> > +
> > + bool DoesFireChangeOnBlur() const {
> > + return IsSingleLineTextControl(false, mType) ||
> > + mType == NS_FORM_INPUT_RANGE;
>
> return DoesFireChangeOnBlur(mType);
Huh. I meant to do that. Thanks. :)
I also renamed DoesFireChangeOnBlur to MayFireChangeOnBlur as discussed on IRC.
Comment 10•12 years ago
|
||
Thanks for fixing this and working on <input type="range">, Jonathan! :)
(In reply to Jonathan Watt [:jwatt] from comment #7)
> (In reply to Mounir Lamouri (:mounir) from comment #6)
> > So, I think we should change an input event whenever the value is changed
> > but we shouldn't follow the behaviour of Webkit and IE10 regarding the
> > change event.
>
> Okay, but, as noted on IRC, we'll not work with the demos that I've seen. We
> can try "fixing the web though". :)
Yeah, this is rather unfortunate. The spec is unfortunately ambiguous enough to allow for both interpretations here. It is difficult to dictate demo assumptions when we're playing catchup.
On the bright side, we will make at least a few developers happy: "Currently the onChange event on my range inputs is firing at each step. Is there a way to stop this event from firing until the user has let go of the slider?" - Randy Marsh from http://stackoverflow.com/questions/5165579/onchange-event-for-html5-range
Assignee | ||
Comment 11•12 years ago
|
||
That's good to hear. :)
Assignee | ||
Comment 12•12 years ago
|
||
(In reply to Mounir Lamouri (:mounir) from comment #6)
> So, I think we shouldn't do that here. IsCallerChrome() works in most
> situations but wouldn't work if the type change is made by a chrome
> privileged caller like Firefox UI.
> I would prefer to not handle this edge case here and open a follow-up
> (blocking the feature shipping) to fix it properly.
Filed bug 851782.
(In reply to Mounir Lamouri (:mounir) from comment #8)
> Also, I would have preferred to not test the input event behaviour in
> test_change_event.html. It would be great if you could create a
> test_input_event.html test. Otherwise, at least file a follow-up for that to
> be done.
Filed bug 851780.
Comment 13•12 years ago
|
||
Assignee | ||
Comment 14•12 years ago
|
||
Backed out for hitting a different assert than the one I mentioned, but at the same two points running test_input_range_mouse_and_touch_events.html as mentioned in comment 4 and comment 5. Stack is:
###!!! ASSERTION: This is unsafe! Fix the caller!: 'Error', file ../../../../content/events/src/nsEventDispatcher.cpp, line 494
nsEventDispatcher::Dispatch
nsEventDispatcher::DispatchDOMEvent
nsINode::DispatchEvent
nsContentUtils::DispatchEvent
nsContentUtils::DispatchTrustedEvent
nsHTMLInputElement::SetValueOfRangeForUserEvent
nsHTMLInputElement::CancelRangeThumbDrag
nsHTMLInputElement::HandleTypeChange
nsHTMLInputElement::ParseAttribute
mozilla::dom::Element::SetAttr
nsGenericHTMLElement::SetAttr
nsGenericHTMLElement::SetAttr
nsGenericHTMLElement::SetAttrHelper
nsHTMLInputElement::SetType
nsIDOMHTMLInputElement_SetType
So basically the issue I filed bug 851782 for, but for some reason this other assertion doesn't trigger on Mac so I didn't notice it.
Assignee | ||
Comment 15•12 years ago
|
||
Repushed with a temporary fix:
https://hg.mozilla.org/integration/mozilla-inbound/rev/3648f5fa5787
What we actually do long term will still be determined in bug 851782.
Comment 16•12 years ago
|
||
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla22
Comment 17•12 years ago
|
||
dev-doc-needed was already set on bug 344618, but I'd like to set it here to ensure that we cover the point about onchange events being fired at different points than in some other browsers. We'll likely keep getting bugs like bug 853670 though.
Keywords: dev-doc-needed
You need to log in
before you can comment on or make changes to this bug.
Description
•