No-JavaScript and no-Customizer support for the new Themes screen.

JavaScript is rarely disabled, but graceful degradation is still important. For example, syntax errors can occur, usually with major WP updates that overhaul entire experiences and update external libraries combined with themes or plugins doing weird or old things. If this error is due to their current theme, a user needs to be able to access the themes screen to switch away from the theme. A more subtle issue could make things painful to diagnose.

This commit renders the grid in PHP (the template is duplicated, but it lightweight, fairly mundane, and easy to sync). On Backbone render, the grid is then re-rendered from JavaScript so searches can occur. Customize and Live Preview is disabled if JS fails to kick in. If JS is disabled, old-school "Preview" links are displayed.

No-Customizer support: The customizer is only supported when the browser supports postMessage (IE8+), and if the frontend is a different domain, CORS (IE10+). We use the .hide-if-no-customize class for this. Pre-customize "Preview" links should use .hide-if-customize.

The .load-customize class should be used to declare a link that opens the customizer. This enables customize-loader.js to intercept this link and load the customizer on top of the current window, making for a smoother experience.

fixes #25964.

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


git-svn-id: http://core.svn.wordpress.org/trunk@26615 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Andrew Nacin 2013-12-06 16:11:10 +00:00
parent 9ecfa135d8
commit df48cebeb4
10 changed files with 84 additions and 20 deletions

View File

@ -6454,7 +6454,7 @@ span.imgedit-scale-warn {
background: #fff;
}
.theme-browser .theme:hover .theme-screenshot img {
.theme-browser.rendered .theme:hover .theme-screenshot img {
opacity: 0.4;
}
@ -6477,7 +6477,7 @@ span.imgedit-scale-warn {
transition: opacity 0.1s ease-in-out;
}
.theme-browser .theme:hover .more-details {
.theme-browser.rendered .theme:hover .more-details {
opacity: 1;
}

File diff suppressed because one or more lines are too long

View File

@ -6454,7 +6454,7 @@ span.imgedit-scale-warn {
background: #fff;
}
.theme-browser .theme:hover .theme-screenshot img {
.theme-browser.rendered .theme:hover .theme-screenshot img {
opacity: 0.4;
}
@ -6477,7 +6477,7 @@ span.imgedit-scale-warn {
transition: opacity 0.1s ease-in-out;
}
.theme-browser .theme:hover .more-details {
.theme-browser.rendered .theme:hover .more-details {
opacity: 1;
}

File diff suppressed because one or more lines are too long

View File

@ -378,9 +378,11 @@ function themes_api( $action, $args = null ) {
* @return array An associative array of theme data, sorted by name.
*/
function wp_prepare_themes_for_js( $themes = null ) {
$prepared_themes = array();
$current_theme = get_stylesheet();
// Make sure the current theme is listed first.
$prepared_themes = array( $current_theme => array() );
if ( null === $themes ) {
$themes = wp_get_themes( array( 'allowed' => true ) );
if ( ! isset( $themes[ $current_theme ] ) ) {
@ -406,7 +408,7 @@ function wp_prepare_themes_for_js( $themes = null ) {
$slug = $theme->get_stylesheet();
$encoded_slug = urlencode( $slug );
$prepared_themes[] = array(
$prepared_themes[ $slug ] = array(
'id' => $slug,
'name' => $theme->display( 'Name' ),
'screenshot' => array( $theme->get_screenshot() ), // @todo multiple
@ -422,6 +424,13 @@ function wp_prepare_themes_for_js( $themes = null ) {
'actions' => array(
'activate' => current_user_can( 'switch_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=activate&stylesheet=' . $encoded_slug ), 'switch-theme_' . $slug ) : null,
'customize'=> current_user_can( 'edit_theme_options' ) ? wp_customize_url( $slug ) : null,
'preview' => add_query_arg( array(
'preview' => 1,
'template' => urlencode( $theme->get_template() ),
'stylesheet' => urlencode( $slug ),
'preview_iframe' => true,
'TB_iframe' => true,
), home_url( '/' ) ),
'delete' => current_user_can( 'delete_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=delete&stylesheet=' . $encoded_slug ), 'delete-theme_' . $slug ) : null,
),
);
@ -436,5 +445,6 @@ function wp_prepare_themes_for_js( $themes = null ) {
*
* @param array $prepared_themes Array of themes.
*/
return apply_filters( 'wp_prepare_themes_for_js', $prepared_themes );
$prepared_themes = apply_filters( 'wp_prepare_themes_for_js', $prepared_themes );
return array_values( $prepared_themes );
}

View File

@ -51,7 +51,7 @@ themes.view.Appearance = wp.Backbone.View.extend({
// Render and append
this.view.render();
this.$el.append( this.view.el );
this.$el.empty().append( this.view.el ).addClass('rendered');
this.$el.append( '<br class="clear"/>' );
},

File diff suppressed because one or more lines are too long

View File

@ -218,7 +218,7 @@ get_current_screen()->set_help_sidebar(
$title = __('Themes');
$parent_file = 'themes.php';
wp_enqueue_script( 'theme' );
wp_enqueue_script( 'theme-preview' );
require_once(ABSPATH . 'wp-admin/admin-header.php');

View File

@ -30,7 +30,7 @@ if ( !is_network_admin() )
$submenu_file = 'themes.php';
wp_enqueue_script( 'theme-install' );
wp_enqueue_script( 'theme' );
wp_enqueue_script( 'theme-preview' );
$body_id = $tab;

View File

@ -116,7 +116,7 @@ require_once( ABSPATH . 'wp-admin/admin-header.php' );
<div class="wrap">
<h2><?php esc_html_e( 'Themes' ); ?>
<span class="theme-count"></span>
<span class="theme-count"><?php echo count( $themes ); ?></span>
<?php if ( ! is_multisite() && current_user_can( 'install_themes' ) ) : ?>
<a href="<?php echo admin_url( 'theme-install.php' ); ?>" class="add-new-h2"><?php echo esc_html( _x( 'Add New', 'Add new theme' ) ); ?></a>
<?php endif; ?>
@ -179,7 +179,54 @@ if ( ! $ct->errors() || ( 1 == count( $ct->errors()->get_error_codes() )
?>
<div class="theme-browser"></div>
<div class="theme-browser">
<div class="themes">
<?php
/*
* This PHP is synchronized with the tmpl-theme template below!
*/
foreach ( $themes as $theme ) : ?>
<div class="theme<?php if ( $theme['active'] ) echo ' active'; ?>">
<?php if ( ! empty( $theme['screenshot'][0] ) ) { ?>
<div class="theme-screenshot">
<img src="<?php echo $theme['screenshot'][0]; ?>" alt="" />
</div>
<?php } else { ?>
<div class="theme-screenshot blank"></div>
<?php } ?>
<span class="more-details"><?php _e( 'Theme Details' ); ?></span>
<div class="theme-author"><?php printf( __( 'By %s' ), $theme['author'] ); ?></div>
<?php if ( $theme['active'] ) { ?>
<h3 class="theme-name"><span><?php _ex( 'Active:', 'theme' ); ?></span> <?php echo $theme['name']; ?></h3>
<?php } else { ?>
<h3 class="theme-name"><?php echo $theme['name']; ?></h3>
<?php } ?>
<div class="theme-actions">
<?php if ( $theme['active'] ) { ?>
<?php if ( $theme['actions']['customize'] ) { ?>
<a class="button button-primary customize load-customize hide-if-no-customize" href="<?php echo $theme['actions']['customize']; ?>"><?php _e( 'Customize' ); ?></a>
<?php } ?>
<?php } else { ?>
<a class="button button-primary activate" href="<?php echo $theme['actions']['activate']; ?>"><?php _e( 'Activate' ); ?></a>
<a class="button button-secondary load-customize hide-if-no-customize" href="<?php echo $theme['actions']['customize']; ?>"><?php _e( 'Live Preview' ); ?></a>
<a class="button button-secondary hide-if-customize" href="<?php echo $theme['actions']['preview']; ?>"><?php _e( 'Preview' ); ?></a>
<?php } ?>
</div>
<?php if ( $theme['hasUpdate'] ) { ?>
<div class="theme-update"><?php _e( 'Update Available' ); ?></div>
<?php } ?>
</div>
<?php endforeach; ?>
<br class="clear" />
</div>
</div>
<?php
// List broken themes, if any.
@ -212,6 +259,11 @@ if ( ! is_multisite() && current_user_can('edit_themes') && $broken_themes = wp_
?>
</div><!-- .wrap -->
<?php
/*
* The tmpl-theme template is synchronized with PHP above!
*/
?>
<script id="tmpl-theme" type="text/template">
<# if ( data.screenshot[0] ) { #>
<div class="theme-screenshot">
@ -233,11 +285,12 @@ if ( ! is_multisite() && current_user_can('edit_themes') && $broken_themes = wp_
<# if ( data.active ) { #>
<# if ( data.actions.customize ) { #>
<a class="button button-primary hide-if-no-customize" href="{{ data.actions.customize }}"><?php _e( 'Customize' ); ?></a>
<a class="button button-primary customize load-customize hide-if-no-customize" href="{{ data.actions.customize }}"><?php _e( 'Customize' ); ?></a>
<# } #>
<# } else { #>
<a class="button button-primary activate" href="{{{ data.actions.activate }}}"><?php _e( 'Activate' ); ?></a>
<a class="button button-secondary preview" href="{{{ data.actions.customize }}}"><?php _e( 'Live Preview' ); ?></a>
<a class="button button-secondary load-customize hide-if-no-customize" href="{{{ data.actions.customize }}}"><?php _e( 'Live Preview' ); ?></a>
<a class="button button-secondary hide-if-customize" href="{{{ data.actions.preview }}}"><?php _e( 'Preview' ); ?></a>
<# } #>
</div>
@ -296,14 +349,15 @@ if ( ! is_multisite() && current_user_can('edit_themes') && $broken_themes = wp_
<div class="theme-actions">
<div class="active-theme">
<a href="{{{ data.actions.customize }}}" class="button button-primary hide-if-no-customize"><?php _e( 'Customize' ); ?></a>
<a href="{{{ data.actions.customize }}}" class="button button-primary customize load-customize hide-if-no-customize"><?php _e( 'Customize' ); ?></a>
<?php echo implode( ' ', $current_theme_actions ); ?>
</div>
<div class="inactive-theme">
<# if ( data.actions.activate ) { #>
<a href="{{{ data.actions.activate }}}" class="button button-primary"><?php _e( 'Activate' ); ?></a>
<a href="{{{ data.actions.activate }}}" class="button button-primary activate"><?php _e( 'Activate' ); ?></a>
<# } #>
<a href="{{{ data.actions.customize }}}" class="button button-secondary"><?php _e( 'Live Preview' ); ?></a>
<a href="{{{ data.actions.customize }}}" class="button button-secondary load-customize hide-if-no-customize"><?php _e( 'Live Preview' ); ?></a>
<a href="{{{ data.actions.preview }}}" class="button button-secondary hide-if-customize"><?php _e( 'Preview' ); ?></a>
</div>
<# if ( ! data.active && data.actions.delete ) { #>