зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1446722: set default value for 'mFocusedValue' for the html input elements 'date' and 'time'. r=smaug
In order to trigger the 'onchange' event when resetting the 'date' or 'time' html input elements. Differential Revision: https://phabricator.services.mozilla.com/D24206 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
033681c09c
Коммит
7558681ee9
|
@ -5662,6 +5662,7 @@ nsresult HTMLInputElement::SetDefaultValueAsValue() {
|
|||
GetDefaultValue(resetVal);
|
||||
|
||||
// SetValueInternal is going to sanitize the value.
|
||||
// TODO(mbrodesser): sanitizing will only happen if `mDoneCreating` is true.
|
||||
return SetValueInternal(resetVal, nsTextEditorState::eSetValue_Internal);
|
||||
}
|
||||
|
||||
|
@ -5673,6 +5674,14 @@ void HTMLInputElement::SetDirectionFromValue(bool aNotify) {
|
|||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsDateOrTime(uint8_t aType) {
|
||||
return (aType == NS_FORM_INPUT_DATE) || (aType == NS_FORM_INPUT_TIME);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLInputElement::Reset() {
|
||||
// We should be able to reset all dirty flags regardless of the type.
|
||||
|
@ -5681,8 +5690,15 @@ HTMLInputElement::Reset() {
|
|||
mLastValueChangeWasInteractive = false;
|
||||
|
||||
switch (GetValueMode()) {
|
||||
case VALUE_MODE_VALUE:
|
||||
return SetDefaultValueAsValue();
|
||||
case VALUE_MODE_VALUE: {
|
||||
nsresult result = SetDefaultValueAsValue();
|
||||
if (IsDateOrTime(mType)) {
|
||||
// mFocusedValue has to be set here, so that `FireChangeEventIfNeeded`
|
||||
// can fire a change event if necessary.
|
||||
GetValue(mFocusedValue, CallerType::System);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case VALUE_MODE_DEFAULT_ON:
|
||||
DoSetChecked(DefaultChecked(), true, false);
|
||||
return NS_OK;
|
||||
|
@ -5917,7 +5933,7 @@ void HTMLInputElement::DoneCreatingElement() {
|
|||
DoSetChecked(DefaultChecked(), false, false);
|
||||
}
|
||||
|
||||
// Sanitize the value.
|
||||
// Sanitize the value and potentially set mFocusedValue.
|
||||
if (GetValueMode() == VALUE_MODE_VALUE) {
|
||||
nsAutoString aValue;
|
||||
GetValue(aValue, CallerType::System);
|
||||
|
@ -5925,6 +5941,12 @@ void HTMLInputElement::DoneCreatingElement() {
|
|||
// may potentially be big, but most likely we've failed to allocate
|
||||
// before the type change.)
|
||||
SetValueInternal(aValue, nsTextEditorState::eSetValue_Internal);
|
||||
|
||||
if (IsDateOrTime(mType)) {
|
||||
// mFocusedValue has to be set here, so that `FireChangeEventIfNeeded` can
|
||||
// fire a change event if necessary.
|
||||
mFocusedValue = aValue;
|
||||
}
|
||||
}
|
||||
|
||||
mShouldInitChecked = false;
|
||||
|
|
|
@ -412,7 +412,9 @@ class HTMLInputElement final : public nsGenericHTMLFormElementWithState,
|
|||
void UpdateValidityUIBits(bool aIsFocused);
|
||||
|
||||
/**
|
||||
* Fires change event if mFocusedValue and current value held are unequal.
|
||||
* Fires change event if mFocusedValue and current value held are unequal and
|
||||
* if a change event may be fired on bluring.
|
||||
* Sets mFocusedValue to value, if a change event is fired.
|
||||
*/
|
||||
void FireChangeEventIfNeeded();
|
||||
|
||||
|
@ -1465,7 +1467,8 @@ class HTMLInputElement final : public nsGenericHTMLFormElementWithState,
|
|||
* when the element is either changed through a script, focused or dispatches
|
||||
* a change event. This is to ensure correct future change event firing.
|
||||
* NB: This is ONLY applicable where the element is a text control. ie,
|
||||
* where type= "text", "email", "search", "tel", "url" or "password".
|
||||
* where type= "date", "time", "text", "email", "search", "tel", "url" or
|
||||
* "password".
|
||||
*/
|
||||
nsString mFocusedValue;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
support-files =
|
||||
save_restore_radio_groups.sjs
|
||||
test_input_number_data.js
|
||||
utils.js
|
||||
!/dom/html/test/reflect.js
|
||||
FAIL.html
|
||||
PASS.html
|
||||
|
@ -39,6 +40,7 @@ skip-if = android_version == '18' # Android, bug 1147974
|
|||
[test_input_datetime_focus_blur_events.html]
|
||||
[test_input_datetime_focus_state.html]
|
||||
[test_input_datetime_hidden.html]
|
||||
[test_input_datetime_reset_default_value_input_change_event.html]
|
||||
[test_input_datetime_tabindex.html]
|
||||
[test_input_defaultValue.html]
|
||||
[test_input_email.html]
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1446722
|
||||
-->
|
||||
<head>
|
||||
<title>Test for bug 1446722</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1446722">Mozilla bug 1446722</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<form>
|
||||
<input type="time" id="input_time" value="10:30" onchange="++numberChangeEvents"
|
||||
oninput="++numberInputEvents">
|
||||
<input type="date" id="input_date" value="2012-05-06" onchange="++numberChangeEvents"
|
||||
oninput="++numberInputEvents">
|
||||
<input type="time" id="input_time2" value="11:30" onchange="++numberChangeEvents"
|
||||
oninput="++numberInputEvents">
|
||||
<input type="date" id="input_date2" value="2014-07-08"
|
||||
onchange="++numberChangeEvents"
|
||||
oninput="++numberInputEvents">
|
||||
<input type="time" id="input_time3" value="12:30" onchange="++numberChangeEvents"
|
||||
oninput="++numberInputEvents">
|
||||
<input type="date" id="input_date3" value="2014-08-09"
|
||||
onchange="++numberChangeEvents"
|
||||
oninput="++numberInputEvents">
|
||||
<input type="reset" id="input_reset">
|
||||
</form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript">
|
||||
|
||||
/**
|
||||
* Test for bug 1446722.
|
||||
*
|
||||
* Test change and input events are fired for date and time inputs when the
|
||||
* default value is reset from the date UI and the time UI.
|
||||
* Test they are not fired when the value is changed via a script.
|
||||
* Test clicking the reset button of a form does not fire these events.
|
||||
**/
|
||||
|
||||
const INPUT_FIELD_ID_PREFIX = "input_";
|
||||
|
||||
var numberChangeEvents = 0;
|
||||
var numberInputEvents = 0;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
if (isDesktopUserAgent(navigator)) {
|
||||
test_reset_in_ui_triggers_change_and_input_event(
|
||||
"time", numberChangeEvents, numberInputEvents);
|
||||
test_reset_in_ui_triggers_change_and_input_event(
|
||||
"date", numberChangeEvents, numberInputEvents);
|
||||
}
|
||||
|
||||
test_reset_in_script_does_not_trigger_change_and_input_event(
|
||||
"time2", numberChangeEvents, numberInputEvents);
|
||||
test_reset_in_script_does_not_trigger_change_and_input_event(
|
||||
"date2", numberChangeEvents, numberInputEvents);
|
||||
|
||||
test_reset_form_does_not_trigger_change_and_input_events("time3", "14:00",
|
||||
numberChangeEvents, numberInputEvents);
|
||||
test_reset_form_does_not_trigger_change_and_input_events("date3", "2016-01-01",
|
||||
numberChangeEvents, numberInputEvents);
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
function test_reset_in_ui_triggers_change_and_input_event(
|
||||
inputFieldIdSuffix, oldNumberChangeEvents, oldNumberInputEvents) {
|
||||
const inputFieldName = INPUT_FIELD_ID_PREFIX + inputFieldIdSuffix;
|
||||
var input = document.getElementById(inputFieldName);
|
||||
|
||||
is(input.value, input.defaultValue,
|
||||
"Check " + inputFieldName + "'s default value is initialized correctly.");
|
||||
is(numberChangeEvents, oldNumberChangeEvents,
|
||||
"Check numberChangeEvents is initialized correctly for " + inputFieldName +
|
||||
".");
|
||||
is(numberInputEvents, oldNumberInputEvents,
|
||||
"Check numberInputEvents is initialized correctly for " + inputFieldName +
|
||||
".");
|
||||
|
||||
simulateUserClicksResetButton(input);
|
||||
|
||||
is(input.value, "",
|
||||
"Check " + inputFieldName + "'s value was set correctly.");
|
||||
is(numberChangeEvents, oldNumberChangeEvents + 1,
|
||||
"Change event should be dispatched for " + inputFieldName + ".");
|
||||
is(numberInputEvents, oldNumberInputEvents + 1,
|
||||
"Input event should be dispatched for " + inputFieldName + ".");
|
||||
}
|
||||
|
||||
function test_reset_in_script_does_not_trigger_change_and_input_event(
|
||||
inputFieldIdSuffix, oldNumberChangeEvents, oldNumberInputEvents) {
|
||||
const inputFieldName = INPUT_FIELD_ID_PREFIX + inputFieldIdSuffix;
|
||||
var input = document.getElementById(inputFieldName);
|
||||
|
||||
is(input.value, input.defaultValue,
|
||||
"Check " + inputFieldName + "'s default value is initialized correctly.");
|
||||
is(numberChangeEvents, oldNumberChangeEvents,
|
||||
"Check numberChangeEvents is initialized correctly for " + inputFieldName +
|
||||
".");
|
||||
is(numberInputEvents, oldNumberInputEvents,
|
||||
"Check numberInputEvents is initialized correctly for " + inputFieldName +
|
||||
".");
|
||||
|
||||
input.value = "";
|
||||
|
||||
is(numberChangeEvents, oldNumberChangeEvents,
|
||||
"Change event should not be dispatched for " + inputFieldName + ".");
|
||||
is(numberInputEvents, oldNumberInputEvents,
|
||||
"Input event should not be dispatched for " + inputFieldName + ".");
|
||||
}
|
||||
|
||||
function test_reset_form_does_not_trigger_change_and_input_events(
|
||||
inputFieldIdSuffix, newValue, oldNumberChangeEvents, oldNumberInputEvents) {
|
||||
const inputFieldName = INPUT_FIELD_ID_PREFIX + inputFieldIdSuffix;
|
||||
const inputFieldResetButtonName = "input_reset";
|
||||
var input = document.getElementById(inputFieldName);
|
||||
|
||||
is(input.value, input.defaultValue,
|
||||
"Check " + inputFieldName + "'s default value is initialized correctly.");
|
||||
isnot(input.defaultValue, newValue, "Check default value differs from newValue for " +
|
||||
inputFieldName + ".");
|
||||
is(numberChangeEvents, oldNumberChangeEvents,
|
||||
"Check numberChangeEvents is initialized correctly for " + inputFieldName +
|
||||
".");
|
||||
is(numberInputEvents, oldNumberInputEvents,
|
||||
"Check numberInputEvents is initialized correctly for " + inputFieldName +
|
||||
".");
|
||||
|
||||
input.value = newValue;
|
||||
|
||||
var resetButton = document.getElementById(inputFieldResetButtonName);
|
||||
synthesizeMouseAtCenter(resetButton, {});
|
||||
|
||||
is(input.value, input.defaultValue, "Check value is reset to default for " +
|
||||
inputFieldName + ".");
|
||||
is(numberChangeEvents, oldNumberChangeEvents,
|
||||
"Change event should not be dispatched for " + inputFieldResetButtonName + ".");
|
||||
is(numberInputEvents, oldNumberInputEvents,
|
||||
"Input event should not be dispatched for " + inputFieldResetButtonName + ".");
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Simulate the user clicks the reset button of the given date or time element.
|
||||
*
|
||||
* @param inputElement A date or time input element of default size.
|
||||
*/
|
||||
function simulateUserClicksResetButton(inputElement) {
|
||||
var inputRectangle = inputElement.getBoundingClientRect();
|
||||
const offsetX = inputRectangle.width - 15;
|
||||
const offsetY = inputRectangle.height / 2;
|
||||
|
||||
synthesizeMouse(inputElement, offsetX, offsetY, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param navigator https://www.w3schools.com/jsref/obj_navigator.asp.
|
||||
* @return true, iff it's a desktop user agent.
|
||||
*/
|
||||
function isDesktopUserAgent(navigator) {
|
||||
return !/Mobile|Tablet/.test(navigator.userAgent);
|
||||
}
|
||||
|
Загрузка…
Ссылка в новой задаче