Customize: Allow 0:00-0:59 in date/time control when 24-hour time used.

* Let min hour be 0 and max be 23 in 24-hour time; let min hour be 1 and max be 12 in 12-hour time.
* Show error notification when an invalid date value is provided, not just when not a future date.
* Fix translation of custom validity message.
* Start checking for validity after all inputs have been initially populated.
* Remove support for being able to enter 24:00.
* Cease forcing date input elements from being casted to integers, to allow for invalid inputs to be detected.

Props westonruter, Presskopp, peterwilsoncc, atachibana for testing.
See #39896, #28721.
Fixes #42373.

Built from https://develop.svn.wordpress.org/trunk@42042


git-svn-id: http://core.svn.wordpress.org/trunk@41876 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Weston Ruter 2017-10-30 16:40:47 +00:00
parent 285c6a57c8
commit ca84147401
5 changed files with 70 additions and 72 deletions

View File

@ -5542,7 +5542,7 @@
control.inputElements = {};
control.invalidDate = false;
_.bindAll( control, 'populateSetting', 'updateDaysForMonth', 'updateMinutesForHour', 'populateDateInputs' );
_.bindAll( control, 'populateSetting', 'updateDaysForMonth', 'populateDateInputs' );
if ( ! control.setting ) {
throw new Error( 'Missing setting' );
@ -5552,34 +5552,35 @@
var input = $( this ), component, element;
component = input.data( 'component' );
element = new api.Element( input );
if ( 'meridian' === component ) {
element.validate = function( value ) {
if ( 'am' !== value && 'pm' !== value ) {
return null;
}
return value;
};
} else {
element.validate = function( value ) {
var val = parseInt( value, 10 );
if ( isNaN( val ) ) {
return null;
}
return val;
};
}
element.bind( control.populateSetting );
control.inputElements[ component ] = element;
control.elements.push( element );
// Add invalid date error once user changes (and has blurred the input).
input.on( 'change', function() {
if ( control.invalidDate ) {
control.notifications.add( new api.Notification( 'invalid_date', {
message: api.l10n.invalidDate
} ) );
}
} );
// Remove the error immediately after validity change.
input.on( 'input', _.debounce( function() {
if ( ! control.invalidDate ) {
control.notifications.remove( 'invalid_date' );
}
} ) );
} );
control.inputElements.month.bind( control.updateDaysForMonth );
control.inputElements.year.bind( control.updateDaysForMonth );
if ( control.params.includeTime ) {
control.inputElements.hour.bind( control.updateMinutesForHour );
}
control.populateDateInputs();
control.setting.bind( control.populateDateInputs );
// Start populating setting after inputs have been populated.
_.each( control.inputElements, function( element ) {
element.bind( control.populateSetting );
} );
},
/**
@ -5629,7 +5630,7 @@
* @return {boolean} If date input fields has error.
*/
validateInputs: function validateInputs() {
var control = this, errorMessage, components;
var control = this, components, validityInput;
control.invalidDate = false;
@ -5638,25 +5639,41 @@
components.push( 'hour', 'minute' );
}
_.each( components, function( component ) {
var element, el, max, min, value;
_.find( components, function( component ) {
var element, max, min, value;
element = control.inputElements[ component ];
validityInput = element.element.get( 0 );
max = parseInt( element.element.attr( 'max' ), 10 );
min = parseInt( element.element.attr( 'min' ), 10 );
value = parseInt( element(), 10 );
control.invalidDate = isNaN( value ) || value > max || value < min;
if ( ! control.invalidDate ) {
element = control.inputElements[ component ];
el = element.element.get( 0 );
max = parseInt( element.element.attr( 'max' ), 10 );
min = parseInt( element.element.attr( 'min' ), 10 );
value = element();
control.invalidDate = value > max || value < min;
errorMessage = control.invalidDate ? api.l10n.invalid + ' ' + component : '';
el.setCustomValidity( errorMessage );
if ( ! control.section() || api.section.has( control.section() ) && api.section( control.section() ).expanded() ) {
_.result( el, 'reportValidity' );
}
validityInput.setCustomValidity( '' );
}
return control.invalidDate;
} );
if ( control.inputElements.meridian && ! control.invalidDate ) {
validityInput = control.inputElements.meridian.element.get( 0 );
if ( 'am' !== control.inputElements.meridian.get() && 'pm' !== control.inputElements.meridian.get() ) {
control.invalidDate = true;
} else {
validityInput.setCustomValidity( '' );
}
}
if ( control.invalidDate ) {
validityInput.setCustomValidity( api.l10n.invalidValue );
} else {
validityInput.setCustomValidity( '' );
}
if ( ! control.section() || api.section.has( control.section() ) && api.section( control.section() ).expanded() ) {
_.result( validityInput, 'reportValidity' );
}
return control.invalidDate;
},
@ -5669,44 +5686,20 @@
updateDaysForMonth: function updateDaysForMonth() {
var control = this, daysInMonth, year, month, day;
month = control.inputElements.month();
year = control.inputElements.year();
day = control.inputElements.day();
month = parseInt( control.inputElements.month(), 10 );
year = parseInt( control.inputElements.year(), 10 );
day = parseInt( control.inputElements.day(), 10 );
if ( month && year ) {
daysInMonth = new Date( year, month, 0 ).getDate();
control.inputElements.day.element.attr( 'max', daysInMonth );
if ( day > daysInMonth ) {
control.inputElements.day( daysInMonth );
control.inputElements.day( String( daysInMonth ) );
}
}
},
/**
* Updates number of minutes according to the hour selected.
*
* @since 4.9.0
* @return {void}
*/
updateMinutesForHour: function updateMinutesForHour() {
var control = this, maxHours = 24, minuteEl;
if ( control.inputElements.meridian ) {
return;
}
minuteEl = control.inputElements.minute.element;
if ( maxHours === control.inputElements.hour() ) {
control.inputElements.minute( 0 );
minuteEl.data( 'default-max', minuteEl.attr( 'max' ) );
minuteEl.attr( 'max', '0' );
} else if ( minuteEl.data( 'default-max' ) ) {
minuteEl.attr( 'max', minuteEl.data( 'default-max' ) );
}
},
/**
* Populate setting value from the inputs.
*
@ -5745,7 +5738,7 @@
};
getElementValue = function( component ) {
var value = control.inputElements[ component ].get();
var value = parseInt( control.inputElements[ component ].get(), 10 );
if ( _.contains( [ 'month', 'day', 'hour', 'minute' ], component ) ) {
value = pad( value, 2 );
@ -5822,7 +5815,9 @@
}
_.each( control.inputElements, function( element, component ) {
element.set( parsed[ component ] );
if ( 'meridian' === component || parseInt( parsed[ component ], 10 ) !== parseInt( element(), 10 ) ) {
element.set( parsed[ component ] );
}
} );
return true;

File diff suppressed because one or more lines are too long

View File

@ -141,8 +141,9 @@ class WP_Customize_Date_Time_Control extends WP_Customize_Control {
<legend class="title-time"><?php esc_html_e( 'Time' ); ?></legend>
<div class="time-fields clear">
<label for="{{ idPrefix }}date-time-hour" class="screen-reader-text"><?php esc_html_e( 'Hour' ); ?></label>
<# var maxHour = data.twelveHourFormat ? 12 : 24; #>
<input id="{{ idPrefix }}date-time-hour" type="number" size="2" autocomplete="off" class="date-input hour" data-component="hour" min="1" max="{{ maxHour }}">
<# var maxHour = data.twelveHourFormat ? 12 : 23; #>
<# var minHour = data.twelveHourFormat ? 1 : 0; #>
<input id="{{ idPrefix }}date-time-hour" type="number" size="2" autocomplete="off" class="date-input hour" data-component="hour" min="{{ minHour }}" max="{{ maxHour }}">
<span class="time-special-char date-time-separator">:</span>
<label for="{{ idPrefix }}date-time-minute" class="screen-reader-text"><?php esc_html_e( 'Minute' ); ?></label>
<input id="{{ idPrefix }}date-time-minute" type="number" size="2" autocomplete="off" class="date-input minute" data-component="minute" min="0" max="59">

View File

@ -599,6 +599,8 @@ function wp_default_scripts( &$scripts ) {
esc_url( admin_url( 'theme-install.php' ) )
),
'publishSettings' => __( 'Publish Settings' ),
'invalidDate' => __( 'Invalid date.' ),
'invalidValue' => __( 'Invalid value.' ),
) );
$scripts->add( 'customize-selective-refresh', "/wp-includes/js/customize-selective-refresh$suffix.js", array( 'jquery', 'wp-util', 'customize-preview' ), false, 1 );

View File

@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
$wp_version = '4.9-beta4-42041';
$wp_version = '4.9-beta4-42042';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.