Customize: Add global notifications area.

* Displays an error notification in the global area when a save attempt is rejected due to invalid settings. An error notification is also displayed when saving fails due to a network error or server error.
* Introduces `wp.customize.Notifications` subclass of `wp.customize.Values` to contain instances of `wp.customize.Notification` and manage their rendering into a container.
* Exposes the global notification area as `wp.customize.notifications` collection instance.
* Updates the `notifications` object on `Control` to use `Notifications` rather than `Values` and to re-use the rendering logic from the former. The old `Control#renderNotifications` method is deprecated.
* Allows notifications to be dismissed by instantiating them with a `dismissible` property.
* Allows `wp.customize.Notification` to be extended with custom templates and `render` functions.
* Triggers a `removed` event on `wp.customize.Values` instances _after_ a value has been removed from the collection.

Props delawski, westonruter, karmatosed, celloexpressions, Fab1en, melchoyce, Kelderic, afercia, adamsilverstein.
See #34893, #39896.
Fixes #35210, #31582, #37727, #37269.


git-svn-id: https://develop.svn.wordpress.org/trunk@41374 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Weston Ruter
2017-09-12 07:02:49 +00:00
parent 84487618eb
commit 594a41666b
10 changed files with 557 additions and 59 deletions
+16 -2
View File
@@ -348,7 +348,7 @@ final class WP_Customize_Manager {
add_action( 'customize_controls_init', array( $this, 'prepare_controls' ) );
add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_control_scripts' ) );
// Render Panel, Section, and Control templates.
// Render Common, Panel, Section, and Control templates.
add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_panel_templates' ), 1 );
add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_section_templates' ), 1 );
add_action( 'customize_controls_print_footer_scripts', array( $this, 'render_control_templates' ), 1 );
@@ -2355,7 +2355,8 @@ final class WP_Customize_Manager {
if ( $update_transactionally && $invalid_setting_count > 0 ) {
$response = array(
'setting_validities' => $setting_validities,
'message' => sprintf( _n( 'There is %s invalid setting.', 'There are %s invalid settings.', $invalid_setting_count ), number_format_i18n( $invalid_setting_count ) ),
/* translators: placeholder is number of invalid settings */
'message' => sprintf( _n( 'Unable to save due to %s invalid setting.', 'Unable to save due to %s invalid settings.', $invalid_setting_count ), number_format_i18n( $invalid_setting_count ) ),
);
return new WP_Error( 'transaction_fail', '', $response );
}
@@ -3183,6 +3184,19 @@ final class WP_Customize_Manager {
) );
$control->print_template();
}
?>
<script type="text/html" id="tmpl-customize-notification">
<li class="notice notice-{{ data.type || 'info' }} {{ data.alt ? 'notice-alt' : '' }} {{ data.dismissible ? 'is-dismissible' : '' }}" data-code="{{ data.code }}" data-type="{{ data.type }}">
{{{ data.message || data.code }}}
<# if ( data.dismissible ) { #>
<button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php _e( 'Dismiss' ); ?></span></button>
<# } #>
</li>
</script>
<?php
/* The following template is obsolete in core but retained for plugins. */
?>
<script type="text/html" id="tmpl-customize-control-notifications">
<ul>
+78 -5
View File
@@ -433,18 +433,26 @@ window.wp = window.wp || {};
* @param {string} id The ID of the item to remove.
*/
remove: function( id ) {
var value;
var value = this.value( id );
if ( this.has( id ) ) {
value = this.value( id );
if ( value ) {
// Trigger event right before the element is removed from the collection.
this.trigger( 'remove', value );
if ( value.extended( api.Value ) )
if ( value.extended( api.Value ) ) {
value.unbind( this._change );
}
delete value.parent;
}
delete this._value[ id ];
delete this._deferreds[ id ];
// Trigger removed event after the item has been eliminated from the collection.
if ( value ) {
this.trigger( 'removed', value );
}
},
/**
@@ -790,6 +798,39 @@ window.wp = window.wp || {};
* @param {*} [params.data=null] - Any additional data.
*/
api.Notification = api.Class.extend(/** @lends wp.customize.Notification.prototype */{
/**
* Template function for rendering the notification.
*
* This will be populated with template option or else it will be populated with template from the ID.
*
* @since 4.9.0
* @var {Function}
*/
template: null,
/**
* ID for the template to render the notification.
*
* @since 4.9.0
* @var {string}
*/
templateId: 'customize-notification',
/**
* Initialize notification.
*
* @since 4.9.0
*
* @param {string} code - Notification code.
* @param {object} params - Notification parameters.
* @param {string} params.message - Message.
* @param {string} [params.type=error] - Type.
* @param {string} [params.setting] - Related setting ID.
* @param {Function} [params.template] - Function for rendering template. If not provided, this will come from templateId.
* @param {string} [params.templateId] - ID for template to render the notification.
* @param {boolean} [params.dismissible] - Whether the notification can be dismissed.
*/
initialize: function( code, params ) {
var _params;
this.code = code;
@@ -799,12 +840,44 @@ window.wp = window.wp || {};
type: 'error',
fromServer: false,
data: null,
setting: null
setting: null,
template: null,
dismissible: false
},
params
);
delete _params.code;
_.extend( this, _params );
},
/**
* Render the notification.
*
* @since 4.9.0
*
* @returns {jQuery} Notification container element.
*/
render: function() {
var notification = this, container, data;
if ( ! notification.template ) {
notification.template = wp.template( notification.templateId );
}
data = _.extend( {}, notification, {
alt: notification.parent && notification.parent.alt
} );
container = $( notification.template( data ) );
if ( notification.dismissible ) {
container.find( '.notice-dismiss' ).on( 'click', function() {
if ( notification.parent ) {
notification.parent.remove( notification.code );
} else {
container.remove();
}
});
}
return container;
}
});
+1
View File
@@ -546,6 +546,7 @@ function wp_default_scripts( &$scripts ) {
'collapseSidebar' => _x( 'Hide Controls', 'label for hide controls button without length constraints' ),
'expandSidebar' => _x( 'Show Controls', 'label for hide controls button without length constraints' ),
'untitledBlogName' => __( '(Untitled)' ),
'serverSaveError' => __( 'Failed connecting to the server. Please try saving again.' ),
// Used for overriding the file types allowed in plupload.
'allowedFiles' => __( 'Allowed Files' ),
) );