Customize: Eliminate use of customize-loader in core so Customizer is opened consistently in top window.

* Open the door for future browser history feature in #28536, which is currently not feasible when customize-loader is used.
* Remove customizer-loader from being used on admin screens for Dashboard, Themes, non-shiny theme install/update.
* Keep the customize-loader functionality available for plugins, for the time being. It may become deprecated.
* Ensure `return` param in customizer links in Themes screen update to reflect `search` updated by `pushState`.
* Persist `return` when reloading Customizer due to theme switch, autosave restoration, or changeset trashing.
* Use `location.replace()` instead of changing `location.href` when trashing.
* Hide theme browser while Themes screen is loading when there is a `search` to prevent flash of unfiltered themes.
* Use throttling instead of debouncing when searching themes to ensure that screen is updated immediately on page load.
* Fix encoding and decoding of `search` param between URL and search field.
* Add support for dismissing autosaves when closing customize-loader, when it is used by plugins.
* Skip sending changeset UUID to customize-loader for population in browser location if changeset branching is not enabled.

See #28536.
Fixes #40254.


git-svn-id: https://develop.svn.wordpress.org/trunk@41797 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Weston Ruter 2017-10-09 16:03:35 +00:00
parent 6c1ec3088a
commit 153dd26c1f
11 changed files with 130 additions and 72 deletions

View File

@ -7,6 +7,10 @@
16.1 - Manage Themes
------------------------------------------------------------------------------*/
body.js .theme-browser.search-loading {
display: none;
}
.theme-browser .themes {
clear: both;
}

View File

@ -64,7 +64,14 @@ class Theme_Installer_Skin extends WP_Upgrader_Skin {
$install_actions = array();
if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
$install_actions['preview'] = '<a href="' . wp_customize_url( $stylesheet ) . '" class="hide-if-no-customize load-customize"><span aria-hidden="true">' . __( 'Live Preview' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Live Preview &#8220;%s&#8221;' ), $name ) . '</span></a>';
$customize_url = add_query_arg(
array(
'theme' => urlencode( $stylesheet ),
'return' => urlencode( admin_url( 'web' === $this->type ? 'theme-install.php' : 'themes.php' ) ),
),
admin_url( 'customize.php' )
);
$install_actions['preview'] = '<a href="' . esc_url( $customize_url ) . '" class="hide-if-no-customize load-customize"><span aria-hidden="true">' . __( 'Live Preview' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Live Preview &#8220;%s&#8221;' ), $name ) . '</span></a>';
}
$install_actions['activate'] = '<a href="' . esc_url( $activate_link ) . '" class="activatelink"><span aria-hidden="true">' . __( 'Activate' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Activate &#8220;%s&#8221;' ), $name ) . '</span></a>';

View File

@ -49,13 +49,20 @@ class Theme_Upgrader_Skin extends WP_Upgrader_Skin {
), admin_url('themes.php') );
$activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet );
$customize_url = add_query_arg(
array(
'theme' => urlencode( $stylesheet ),
'return' => urlencode( admin_url( 'themes.php' ) ),
),
admin_url( 'customize.php' )
);
if ( get_stylesheet() == $stylesheet ) {
if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
$update_actions['preview'] = '<a href="' . wp_customize_url( $stylesheet ) . '" class="hide-if-no-customize load-customize"><span aria-hidden="true">' . __( 'Customize' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Customize &#8220;%s&#8221;' ), $name ) . '</span></a>';
$update_actions['preview'] = '<a href="' . esc_url( $customize_url ) . '" class="hide-if-no-customize load-customize"><span aria-hidden="true">' . __( 'Customize' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Customize &#8220;%s&#8221;' ), $name ) . '</span></a>';
}
} elseif ( current_user_can( 'switch_themes' ) ) {
if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
$update_actions['preview'] = '<a href="' . wp_customize_url( $stylesheet ) . '" class="hide-if-no-customize load-customize"><span aria-hidden="true">' . __( 'Live Preview' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Live Preview &#8220;%s&#8221;' ), $name ) . '</span></a>';
$update_actions['preview'] = '<a href="' . esc_url( $customize_url ) . '" class="hide-if-no-customize load-customize"><span aria-hidden="true">' . __( 'Live Preview' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Live Preview &#8220;%s&#8221;' ), $name ) . '</span></a>';
}
$update_actions['activate'] = '<a href="' . esc_url( $activate_link ) . '" class="activatelink"><span aria-hidden="true">' . __( 'Activate' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Activate &#8220;%s&#8221;' ), $name ) . '</span></a>';
}

View File

@ -16,8 +16,6 @@ wp_dashboard_setup();
wp_enqueue_script( 'dashboard' );
if ( current_user_can( 'edit_theme_options' ) )
wp_enqueue_script( 'customize-loader' );
if ( current_user_can( 'install_plugins' ) ) {
wp_enqueue_script( 'plugin-install' );
wp_enqueue_script( 'updates' );

View File

@ -106,7 +106,7 @@
*
* @since 4.9.0
*
* @param {string|wp.customize.Notification} - Notification object to add. Alternatively code may be supplied, and in that case the second notificationObject argument must be supplied.
* @param {string|wp.customize.Notification} notification - Notification object to add. Alternatively code may be supplied, and in that case the second notificationObject argument must be supplied.
* @param {wp.customize.Notification} [notificationObject] - Notification to add when first argument is the code string.
* @returns {wp.customize.Notification} Added notification (or existing instance if it was already added).
*/
@ -3014,7 +3014,8 @@
api.utils.parseQueryString( urlParser.search.substr( 1 ) ),
{
theme: themeId,
changeset_uuid: api.settings.changeset.uuid
changeset_uuid: api.settings.changeset.uuid,
'return': api.settings.url['return']
}
);
@ -3044,7 +3045,7 @@
request.done( function() {
deferred.resolve();
$( window ).off( 'beforeunload.customize-confirm' );
window.location.href = urlParser.href; // @todo Use location.replace()?
location.replace( urlParser.href );
} );
request.fail( function() {
@ -6958,7 +6959,9 @@
if ( 'changeset_already_published' === response.code && response.next_changeset_uuid ) {
api.settings.changeset.uuid = response.next_changeset_uuid;
api.state( 'changesetStatus' ).set( '' );
parent.send( 'changeset-uuid', api.settings.changeset.uuid );
if ( api.settings.changeset.branching ) {
parent.send( 'changeset-uuid', api.settings.changeset.uuid );
}
api.previewer.send( 'changeset-uuid', api.settings.changeset.uuid );
}
} );
@ -6989,7 +6992,9 @@
api.state( 'changesetStatus' ).set( '' );
api.settings.changeset.uuid = response.next_changeset_uuid;
parent.send( 'changeset-uuid', api.settings.changeset.uuid );
if ( api.settings.changeset.branching ) {
parent.send( 'changeset-uuid', api.settings.changeset.uuid );
}
}
// Prevent subsequent requestChangesetUpdate() calls from including the settings that have been saved.
@ -7065,6 +7070,7 @@
urlParser.href = location.href;
queryParams = api.utils.parseQueryString( urlParser.search.substr( 1 ) );
delete queryParams.changeset_uuid;
queryParams['return'] = api.settings.url['return'];
urlParser.search = $.param( queryParams );
location.replace( urlParser.href );
};
@ -7418,6 +7424,7 @@
} else {
queryParams.customize_autosaved = 'on';
}
queryParams['return'] = api.settings.url['return'];
urlParser.search = $.param( queryParams );
return urlParser.href;
}
@ -7915,16 +7922,9 @@
}
api.bind( 'change', startPromptingBeforeUnload );
closeBtn.on( 'click.customize-controls-close', function( event ) {
function requestClose() {
var clearedToClose = $.Deferred();
event.preventDefault();
/*
* The isInsideIframe condition is because Customizer is not able to use a confirm()
* since customize-loader.js will also use one. So autosave restorations are disabled
* when customize-loader.js is used.
*/
if ( isInsideIframe || isCleanState() ) {
if ( isCleanState() ) {
clearedToClose.resolve();
} else if ( confirm( api.l10n.saveAlert ) ) {
@ -7954,15 +7954,27 @@
} else {
clearedToClose.reject();
}
return clearedToClose.promise();
}
clearedToClose.done( function() {
$( window ).off( 'beforeunload.customize-confirm' );
if ( isInsideIframe ) {
parent.send( 'close' );
} else {
window.location.href = closeBtn.prop( 'href' );
}
parent.bind( 'confirm-close', function() {
requestClose().done( function() {
parent.send( 'confirmed-close', true );
} ).fail( function() {
parent.send( 'confirmed-close', false );
} );
} );
closeBtn.on( 'click.customize-controls-close', function( event ) {
event.preventDefault();
if ( isInsideIframe ) {
parent.send( 'close' ); // See confirm-close logic above.
} else {
requestClose().done( function() {
$( window ).off( 'beforeunload.customize-confirm' );
window.location.href = closeBtn.prop( 'href' );
} );
}
});
})();
@ -7978,7 +7990,9 @@
parent.send( 'title', newTitle );
});
parent.send( 'changeset-uuid', api.settings.changeset.uuid );
if ( api.settings.changeset.branching ) {
parent.send( 'changeset-uuid', api.settings.changeset.uuid );
}
// Initialize the connection with the parent frame.
parent.send( 'ready' );

View File

@ -77,6 +77,8 @@ themes.view.Appearance = wp.Backbone.View.extend({
// Render search form.
this.search();
this.$el.removeClass( 'search-loading' );
// Render and append
this.view.render();
this.$el.empty().append( this.view.el ).addClass( 'rendered' );
@ -1345,17 +1347,15 @@ themes.view.Search = wp.Backbone.View.extend({
event.target.value = '';
}
/**
* Since doSearch is debounced, it will only run when user input comes to a rest
*/
// Note that doSearch is throttled.
this.doSearch( event );
},
// Runs a search on the theme collection.
doSearch: _.debounce( function( event ) {
doSearch: _.throttle( function( event ) {
var options = {};
this.collection.doSearch( event.target.value );
this.collection.doSearch( event.target.value.replace( /\+/g, ' ' ) );
// if search is initiated and key is not return
if ( this.searching && event.which !== 13 ) {
@ -1376,7 +1376,7 @@ themes.view.Search = wp.Backbone.View.extend({
var url = themes.router.baseUrl( '' );
if ( event.target.value ) {
url = themes.router.baseUrl( themes.router.searchPath + event.target.value );
url = themes.router.baseUrl( themes.router.searchPath + encodeURIComponent( event.target.value ) );
}
this.searching = false;
@ -1385,6 +1385,22 @@ themes.view.Search = wp.Backbone.View.extend({
}
});
/**
* Navigate router.
*
* @since 4.9.0
*
* @param {string} url - URL to navigate to.
* @param {object} state - State.
* @returns {void}
*/
function navigateRouter( url, state ) {
var router = this;
if ( Backbone.history._hasPushState ) {
Backbone.Router.prototype.navigate.call( router, url, state );
}
}
// Sets up the routes events for relevant url queries
// Listens to [theme] and [search] params
themes.Router = Backbone.Router.extend({
@ -1405,18 +1421,14 @@ themes.Router = Backbone.Router.extend({
searchPath: '?search=',
search: function( query ) {
$( '.wp-filter-search' ).val( query );
$( '.wp-filter-search' ).val( query.replace( /\+/g, ' ' ) );
},
themes: function() {
$( '.wp-filter-search' ).val( '' );
},
navigate: function() {
if ( Backbone.history._hasPushState ) {
Backbone.Router.prototype.navigate.apply( this, arguments );
}
}
navigate: navigateRouter
});
@ -1508,7 +1520,7 @@ themes.view.InstallerSearch = themes.view.Search.extend({
this.doSearch( event.target.value );
},
doSearch: _.debounce( function( value ) {
doSearch: _.throttle( function( value ) {
var request = {};
// Don't do anything if the search terms haven't changed.
@ -1551,7 +1563,7 @@ themes.view.InstallerSearch = themes.view.Search.extend({
this.collection.query( request );
// Set route
themes.router.navigate( themes.router.baseUrl( themes.router.searchPath + value ), { replace: true } );
themes.router.navigate( themes.router.baseUrl( themes.router.searchPath + encodeURIComponent( value ) ), { replace: true } );
}, 500 )
});
@ -1887,14 +1899,10 @@ themes.InstallerRouter = Backbone.Router.extend({
searchPath: '?search=',
search: function( query ) {
$( '.wp-filter-search' ).val( query );
$( '.wp-filter-search' ).val( query.replace( /\+/g, ' ' ) );
},
navigate: function() {
if ( Backbone.history._hasPushState ) {
Backbone.Router.prototype.navigate.apply( this, arguments );
}
}
navigate: navigateRouter
});
@ -2003,6 +2011,19 @@ $( document ).ready(function() {
themes.Run.init();
}
// Update the return param just in time.
$( document.body ).on( 'click', '.load-customize', function() {
var link = $( this ), urlParser = document.createElement( 'a' );
urlParser.href = link.prop( 'href' );
urlParser.search = $.param( _.extend(
wp.customize.utils.parseQueryString( urlParser.search.substr( 1 ) ),
{
'return': window.location.href
}
) );
link.prop( 'href', urlParser.href );
});
$( '.broken-themes .delete-theme' ).on( 'click', function() {
return confirm( _wpThemeSettings.settings.confirmDelete );
});

View File

@ -146,14 +146,13 @@ wp_localize_script( 'theme', '_wpThemeSettings', array(
add_thickbox();
wp_enqueue_script( 'theme' );
wp_enqueue_script( 'updates' );
wp_enqueue_script( 'customize-loader' );
require_once( ABSPATH . 'wp-admin/admin-header.php' );
?>
<div class="wrap">
<h1 class="wp-heading-inline"><?php esc_html_e( 'Themes' ); ?>
<span class="title-count theme-count"><?php echo count( $themes ); ?></span>
<span class="title-count theme-count"><?php echo ! empty( $_GET['search'] ) ? __( '&hellip;' ) : count( $themes ); ?></span>
</h1>
<?php if ( ! is_multisite() && current_user_can( 'install_themes' ) ) : ?>
@ -234,7 +233,13 @@ if ( ! $ct->errors() || ( 1 == count( $ct->errors()->get_error_codes() )
?>
<div class="theme-browser">
<?php
$class_name = 'theme-browser';
if ( ! empty( $_GET['search'] ) ) {
$class_name .= ' search-loading';
}
?>
<div class="<?php echo esc_attr( $class_name ); ?>">
<div class="themes wp-clearfix">
<?php

View File

@ -173,7 +173,6 @@ if ( isset($_GET['action']) ) {
check_admin_referer('upgrade-theme_' . $theme);
wp_enqueue_script( 'customize-loader' );
wp_enqueue_script( 'updates' );
$title = __('Update Theme');
@ -223,10 +222,9 @@ if ( isset($_GET['action']) ) {
check_admin_referer( 'install-theme_' . $theme );
$api = themes_api('theme_information', array('slug' => $theme, 'fields' => array('sections' => false, 'tags' => false) ) ); //Save on a bit of bandwidth.
if ( is_wp_error($api) )
wp_die($api);
wp_enqueue_script( 'customize-loader' );
if ( is_wp_error( $api ) ) {
wp_die( $api );
}
$title = __('Install Themes');
$parent_file = 'themes.php';
@ -253,8 +251,6 @@ if ( isset($_GET['action']) ) {
$file_upload = new File_Upload_Upgrader('themezip', 'package');
wp_enqueue_script( 'customize-loader' );
$title = __('Upload Theme');
$parent_file = 'themes.php';
$submenu_file = 'theme-install.php';

View File

@ -4236,6 +4236,7 @@ final class WP_Customize_Manager {
),
'url' => array(
'preview' => esc_url_raw( $this->get_preview_url() ),
'return' => esc_url_raw( $this->get_return_url() ),
'parent' => esc_url_raw( admin_url() ),
'activated' => esc_url_raw( home_url( '/' ) ),
'ajax' => esc_url_raw( admin_url( 'admin-ajax.php', 'relative' ) ),

View File

@ -1,4 +1,4 @@
/* global _wpCustomizeLoaderSettings, confirm */
/* global _wpCustomizeLoaderSettings */
/**
* Expose a public API that allows the customizer to be
* loaded on any page.
@ -208,25 +208,30 @@ window.wp = window.wp || {};
* Close the Customizer overlay.
*/
close: function() {
if ( ! this.active ) {
var self = this, onConfirmClose;
if ( ! self.active ) {
return;
}
// Display AYS dialog if Customizer is dirty
if ( ! this.saved() && ! confirm( Loader.settings.l10n.saveAlert ) ) {
// Go forward since Customizer is exited by history.back()
history.forward();
return;
}
onConfirmClose = function( confirmed ) {
if ( confirmed ) {
self.active = false;
self.trigger( 'close' );
this.active = false;
// Restore document title prior to opening the Live Preview
if ( self.originalDocumentTitle ) {
document.title = self.originalDocumentTitle;
}
} else {
this.trigger( 'close' );
// Go forward since Customizer is exited by history.back()
history.forward();
}
self.messenger.unbind( 'confirmed-close', onConfirmClose );
};
self.messenger.bind( 'confirmed-close', onConfirmClose );
// Restore document title prior to opening the Live Preview
if ( this.originalDocumentTitle ) {
document.title = this.originalDocumentTitle;
}
Loader.messenger.send( 'confirm-close' );
},
/**

View File

@ -725,7 +725,7 @@ function wp_default_scripts( &$scripts ) {
$scripts->add( 'text-widgets', "/wp-admin/js/widgets/text-widgets$suffix.js", array( 'jquery', 'backbone', 'editor', 'wp-util', 'wp-a11y' ) );
$scripts->add( 'custom-html-widgets', "/wp-admin/js/widgets/custom-html-widgets$suffix.js", array( 'code-editor', 'jquery', 'backbone', 'wp-util', 'jquery-ui-core', 'wp-a11y' ) );
$scripts->add( 'theme', "/wp-admin/js/theme$suffix.js", array( 'wp-backbone', 'wp-a11y' ), false, 1 );
$scripts->add( 'theme', "/wp-admin/js/theme$suffix.js", array( 'wp-backbone', 'wp-a11y', 'customize-base' ), false, 1 );
$scripts->add( 'inline-edit-post', "/wp-admin/js/inline-edit-post$suffix.js", array( 'jquery', 'tags-suggest', 'wp-a11y' ), false, 1 );
did_action( 'init' ) && $scripts->localize( 'inline-edit-post', 'inlineEditL10n', array(