<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[31533] trunk/src: Add theme browsing and theme switching to the Customizer</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/31533">31533</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/31533","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>markjaquith</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2015-02-24 20:30:22 +0000 (Tue, 24 Feb 2015)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Add theme browsing and theme switching to the Customizer
* Brings into core the Customizer Theme Switcher feature plugin
* You can now browse, preview, and activate themes right from the Customizer
fixes <a href="https://core.trac.wordpress.org/ticket/31303">#31303</a>.
props celloexpressions, afercia, westonruter, folletto, designsimply</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpadmincsscustomizecontrolscss">trunk/src/wp-admin/css/customize-controls.css</a></li>
<li><a href="#trunksrcwpadmincustomizephp">trunk/src/wp-admin/customize.php</a></li>
<li><a href="#trunksrcwpadminincludesthemephp">trunk/src/wp-admin/includes/theme.php</a></li>
<li><a href="#trunksrcwpadminjscustomizecontrolsjs">trunk/src/wp-admin/js/customize-controls.js</a></li>
<li><a href="#trunksrcwpincludesadminbarphp">trunk/src/wp-includes/admin-bar.php</a></li>
<li><a href="#trunksrcwpincludesclasswpcustomizecontrolphp">trunk/src/wp-includes/class-wp-customize-control.php</a></li>
<li><a href="#trunksrcwpincludesclasswpcustomizemanagerphp">trunk/src/wp-includes/class-wp-customize-manager.php</a></li>
<li><a href="#trunksrcwpincludesclasswpcustomizesectionphp">trunk/src/wp-includes/class-wp-customize-section.php</a></li>
<li><a href="#trunksrcwpincludesversionphp">trunk/src/wp-includes/version.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpadmincsscustomizecontrolscss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/css/customize-controls.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/css/customize-controls.css 2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-admin/css/customize-controls.css 2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -827,7 +827,177 @@
</span><span class="cx" style="display: block; padding: 0 10px"> float: right;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Themes
+ */
+@-webkit-keyframes customize-reload {
+ 0% { opacity: 0; }
+ 100% { opacity: 1; }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+@-moz-keyframes customize-reload {
+ 0% { opacity: 0; }
+ 100% { opacity: 1; }
+}
+
+@keyframes customize-reload {
+ 0% { opacity: 0; }
+ 100% { opacity: 1; }
+}
+
+/* #customize-container is reused from customize-loader.js, hence the naming. */
+.wp-customizer .customize-loading #customize-container {
+ display: block;
+ -webkit-animation: customize-reload .75s; /* Can't use `transition` because `display` changes here. */
+ -moz-animation: customize-reload .75s;
+ animation: customize-reload .75s;
+}
+
+.customize-themes-panel {
+ display: none;
+ padding: 0 8px;
+ background: #f1f1f1;
+ box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+}
+
+.control-section.open .customize-themes-panel {
+ display: block;
+}
+
+#customize-theme-controls .customize-themes-panel .accordion-section-content {
+ background: transparent;
+ display: block;
+}
+
+.customize-control.customize-control-theme {
+ margin-bottom: 8px;
+}
+
+.wp-customizer .theme-browser .themes {
+ padding-bottom: 8px;
+}
+
+.wp-customizer .theme-browser .theme {
+ margin: 0;
+ width: 100%;
+}
+
+.wp-customizer .theme-browser .theme .theme-actions {
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+ opacity: 1;
+}
+
+#customize-controls h3.theme-name {
+ font-size: 15px;
+}
+
+.wp-customizer .theme-browser .theme.active .theme-name {
+ padding-right: 15px;
+}
+
+.wp-customizer #themes-filter {
+ width: 100%;
+}
+
+/* Panel-like behavior */
+#accordion-section-themes .accordion-section-title:after {
+ content: "\f148";
+}
+
+.rtl #accordion-section-themes .accordion-section-title:after {
+ -webkit-transform: rotate(180deg);
+ -ms-transform: rotate(180deg);
+ transform: rotate(180deg);
+}
+
+#customize-theme-controls .control-section.current-panel > h3.accordion-section-title {
+ left: 0;
+}
+
+.customize-themes-panel.control-panel-content {
+ position: absolute;
+ left: -100%;
+ top: 0;
+ width: 100%;
+ border-top: 1px solid #ddd;
+}
+
+.in-themes-panel #customize-info,
+.in-themes-panel #customize-theme-controls > ul > .accordion-section {
+ left: 100%;
+}
+
+.themes-panel-back:before {
+ top: 13px;
+ left: 14px;
+}
+
+.in-themes-panel .themes-panel-back {
+ left: 0;
+}
+
+.in-sub-panel .themes-panel-back {
+ display: none;
+}
+
+.control-panel-back.themes-panel-back:before {
+ content: "\f345";
+}
+
+.rtl .control-panel-back.themes-panel-back:before {
+ content: "\f341";
+}
+
+/* Details View */
+.wp-customizer .theme-overlay {
+ display: none;
+}
+
+.wp-customizer.modal-open .theme-overlay {
+ position: fixed;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 109;
+}
+
+.wp-customizer .theme-overlay .theme-backdrop {
+ background: rgba( 238, 238, 238, 0.75 );
+ position: fixed;
+ z-index: 110;
+}
+
+.wp-customizer .theme-overlay .theme-wrap {
+ left: 90px;
+ right: 90px;
+ top: 45px;
+ bottom: 45px;
+ z-index: 120;
+ max-width: 1740px; /* To ensure that theme screenshots are not displayed larger than 880px wide. */
+}
+
+.wp-customizer .theme-overlay .theme-actions {
+ text-align: right; /* Because there's only one action, match the pattern of media modals and right-align the action. */
+}
+
+.modal-open .in-themes-panel #customize-controls .wp-full-overlay-sidebar-content {
+ overflow: visible; /* Prevent the top-level Customizer controls from becoming visible when elements on the right of the details modal are focused. */
+}
+
+/* Small Screens */
+@media (max-width:850px), (max-height:472px) {
+ .wp-customizer .theme-overlay .theme-wrap {
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ }
+}
+
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /** Handle cheaters. */
</span><span class="cx" style="display: block; padding: 0 10px"> body.cheatin {
</span><span class="cx" style="display: block; padding: 0 10px"> font-size: medium;
</span></span></pre></div>
<a id="trunksrcwpadmincustomizephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/customize.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/customize.php 2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-admin/customize.php 2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -136,40 +136,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <span class="control-panel-back" tabindex="-1"><span class="screen-reader-text"><?php _e( 'Back' ); ?></span></span>
</span><span class="cx" style="display: block; padding: 0 10px"> </div>
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- <?php
- $screenshot = $wp_customize->theme()->get_screenshot();
- $cannot_expand = ! ( $wp_customize->is_theme_active() || $screenshot || $wp_customize->theme()->get('Description') );
- ?>
-
</del><span class="cx" style="display: block; padding: 0 10px"> <div id="widgets-right"><!-- For Widget Customizer, many widgets try to look for instances under div#widgets-right, so we have to add that ID to a container div in the Customizer for compat -->
</span><span class="cx" style="display: block; padding: 0 10px"> <div class="wp-full-overlay-sidebar-content" tabindex="-1">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- <div id="customize-info" class="accordion-section <?php if ( $cannot_expand ) echo ' cannot-expand'; ?>">
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <div id="customize-info" class="accordion-section">
</ins><span class="cx" style="display: block; padding: 0 10px"> <div class="accordion-section-title" aria-label="<?php esc_attr_e( 'Customizer Options' ); ?>" tabindex="0">
</span><span class="cx" style="display: block; padding: 0 10px"> <span class="preview-notice"><?php
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( ! $wp_customize->is_theme_active() ) {
- /* translators: %s is the theme name in the Customize/Live Preview pane */
- echo sprintf( __( 'You are previewing %s' ), '<strong class="theme-name">' . $wp_customize->theme()->display('Name') . '</strong>' );
- } else {
- /* translators: %s is the site/panel title in the Customize pane */
- echo sprintf( __( 'You are customizing %s' ), '<strong class="theme-name site-title">' . get_bloginfo( 'name' ) . '</strong>' );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ echo sprintf( __( 'You are customizing %s' ), '<strong class="theme-name site-title">' . get_bloginfo( 'name' ) . '</strong>' );
</ins><span class="cx" style="display: block; padding: 0 10px"> ?></span>
</span><span class="cx" style="display: block; padding: 0 10px"> </div>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- <?php if ( ! $cannot_expand ) : ?>
- <div class="accordion-section-content">
- <?php if ( ! $wp_customize->is_theme_active() ) :
- if ( $screenshot ) : ?>
- <img class="theme-screenshot" src="<?php echo esc_url( $screenshot ); ?>" />
- <?php endif; ?>
-
- <?php if ( $wp_customize->theme()->get('Description') ): ?>
- <div class="theme-description"><?php echo $wp_customize->theme()->display('Description'); ?></div>
- <?php endif;
- else:
- echo __( 'The Customizer allows you to preview changes to your site before publishing them. You can also navigate to different pages on your site to preview them.' );
- endif; ?>
- </div>
- <?php endif; ?>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <div class="accordion-section-content"><?php
+ echo __( 'The Customizer allows you to preview changes to your site before publishing them. You can also navigate to different pages on your site to preview them.' );
+ ?></div>
</ins><span class="cx" style="display: block; padding: 0 10px"> </div>
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> <div id="customize-theme-controls">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -246,7 +223,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'url' => array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'preview' => esc_url_raw( $url ? $url : home_url( '/' ) ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'parent' => esc_url_raw( admin_url() ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'activated' => esc_url_raw( admin_url( 'themes.php?activated=true&previewed' ) ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'activated' => esc_url_raw( home_url( '/' ) ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 'ajax' => esc_url_raw( admin_url( 'admin-ajax.php', 'relative' ) ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'allowed' => array_map( 'esc_url_raw', $allowed_urls ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'isCrossDomain' => $cross_domain,
</span></span></pre></div>
<a id="trunksrcwpadminincludesthemephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/theme.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/theme.php 2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-admin/includes/theme.php 2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -486,3 +486,58 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $prepared_themes = apply_filters( 'wp_prepare_themes_for_js', $prepared_themes );
</span><span class="cx" style="display: block; padding: 0 10px"> return array_values( $prepared_themes );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+/**
+ * Print JS templates for the theme-browsing UI in the Customizer.
+ *
+ * @since 4.2.0
+ */
+function customize_themes_print_templates() {
+ ?>
+ <script type="text/html" id="tmpl-customize-themes-details-view">
+ <div class="theme-backdrop"></div>
+ <div class="theme-wrap">
+ <div class="theme-header">
+ <button type="button" class="left dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Show previous theme' ); ?></span></button>
+ <button type="button" class="right dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Show next theme' ); ?></span></button>
+ <button type="button" class="close dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Close details dialog' ); ?></span></button>
+ </div>
+ <div class="theme-about">
+ <div class="theme-screenshots">
+ <# if ( data.screenshot[0] ) { #>
+ <div class="screenshot"><img src="{{ data.screenshot[0] }}" alt="" /></div>
+ <# } else { #>
+ <div class="screenshot blank"></div>
+ <# } #>
+ </div>
+
+ <div class="theme-info">
+ <# if ( data.active ) { #>
+ <span class="current-label"><?php _e( 'Current Theme' ); ?></span>
+ <# } #>
+ <h3 class="theme-name">{{{ data.name }}}<span class="theme-version"><?php printf( __( 'Version: %s' ), '{{ data.version }}' ); ?></span></h3>
+ <h4 class="theme-author"><?php printf( __( 'By %s' ), '{{{ data.authorAndUri }}}' ); ?></h4>
+ <p class="theme-description">{{{ data.description }}}</p>
+
+ <# if ( data.parent ) { #>
+ <p class="parent-theme"><?php printf( __( 'This is a child theme of %s.' ), '<strong>{{{ data.parent }}}</strong>' ); ?></p>
+ <# } #>
+
+ <# if ( data.tags ) { #>
+ <p class="theme-tags"><span><?php _e( 'Tags:' ); ?></span> {{ data.tags }}</p>
+ <# } #>
+ </div>
+ </div>
+
+ <div class="theme-actions">
+ <# if ( ! data.active ) { #>
+ <div class="inactive-theme">
+ <a href="<?php echo add_query_arg( 'theme', '{{ data.id }}', remove_query_arg( 'theme' ) ); ?>" target="_top" class="button button-primary"><?php _e( 'Live Preview' ); ?></a>
+ </div>
+ <# } #>
+ </div>
+ </div>
+ </script>
+ <?php
+}
+add_action( 'customize_controls_print_footer_scripts', 'customize_themes_print_templates' );
</ins></span></pre></div>
<a id="trunksrcwpadminjscustomizecontrolsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/js/customize-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/js/customize-controls.js 2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-admin/js/customize-controls.js 2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -521,6 +521,351 @@
</span><span class="cx" style="display: block; padding: 0 10px"> });
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * wp.customize.ThemesSection
+ *
+ * Custom section for themes that functions similarly to a backwards panel,
+ * and also handles the theme-details view rendering and navigation.
+ *
+ * @constructor
+ * @augments wp.customize.Section
+ * @augments wp.customize.Container
+ */
+ api.ThemesSection = api.Section.extend({
+ currentTheme: '',
+ overlay: '',
+ template: '',
+
+ /**
+ * @since 4.2.0
+ */
+ ready: function () {
+ var section = this;
+ section.overlay = section.container.find( '.theme-overlay' );
+ section.template = wp.template( 'customize-themes-details-view' );
+
+ // Bind global keyboard events.
+ $( 'body' ).on( 'keyup', function( event ) {
+ if ( ! section.overlay.find( '.theme-wrap' ).is( ':visible' ) ) {
+ return;
+ }
+
+ // Pressing the right arrow key fires a theme:next event
+ if ( 39 === event.keyCode ) {
+ section.nextTheme();
+ }
+
+ // Pressing the left arrow key fires a theme:previous event
+ if ( 37 === event.keyCode ) {
+ section.previousTheme();
+ }
+
+ // Pressing the escape key fires a theme:collapse event
+ if ( 27 === event.keyCode ) {
+ section.closeDetails();
+ }
+ });
+ },
+
+ /**
+ * @since 4.2.0
+ */
+ attachEvents: function () {
+ var meta, section = this;
+
+ // Expand/Collapse section/panel.
+ section.container.find( '.accordion-section-title' ).on( 'click keydown', function( event ) {
+ if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+ return;
+ }
+ event.preventDefault(); // Keep this AFTER the key filter above
+
+ if ( section.expanded() ) {
+ section.collapse();
+ } else {
+ section.expand();
+ }
+ });
+
+ section.container.find( '.themes-panel-back' ).on( 'click keydown', function( event ) {
+ if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+ return;
+ }
+
+ event.preventDefault(); // Keep this AFTER the key filter above
+
+ section.collapse();
+ });
+
+ // Theme navigation in details view.
+ section.container.on( 'click keydown', '.left', function( event ) {
+ if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+ return;
+ }
+
+ event.preventDefault(); // Keep this AFTER the key filter above
+
+ section.previousTheme();
+ });
+
+ section.container.on( 'click keydown', '.right', function( event ) {
+ if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+ return;
+ }
+
+ event.preventDefault(); // Keep this AFTER the key filter above
+
+ section.nextTheme();
+ });
+
+ section.container.on( 'click keydown', '.theme-backdrop, .close', function( event ) {
+ if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+ return;
+ }
+
+ event.preventDefault(); // Keep this AFTER the key filter above
+
+ section.closeDetails();
+ });
+
+ section.container.on( 'click keydown', '.theme-actions .button', function( event ) {
+ if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+ return;
+ }
+
+ $( '.wp-full-overlay' ).addClass( 'customize-loading' );
+ });
+
+ section.container.on( 'input', '#themes-filter', function( event ) {
+ var term = event.currentTarget.value.toLowerCase().trim().replace( '-', ' ' ),
+ controls = section.controls();
+ controls.pop(); // Remove the last control (the add-new control).
+ _.each( controls, function( control ) {
+ control.filter( term );
+ });
+ // Update theme count. Note that the add-theme tile is a div.customize-control.
+ count = section.container.find( 'li.customize-control:visible' ).length;
+ section.container.find( '.theme-count' ).text( count );
+ });
+ },
+
+ /**
+ * Update UI to reflect expanded state
+ *
+ * @since 4.2.0
+ *
+ * @param {Boolean} expanded
+ * @param {Object} args
+ * @param {Boolean} args.unchanged
+ * @param {Callback} args.completeCallback
+ */
+ onChangeExpanded: function ( expanded, args ) {
+
+ // Immediately call the complete callback if there were no changes
+ if ( args.unchanged ) {
+ if ( args.completeCallback ) {
+ args.completeCallback();
+ }
+ return;
+ }
+
+ // Note: there is a second argument 'args' passed
+ var position, scroll,
+ panel = this,
+ section = panel.container.closest( '.accordion-section' ),
+ overlay = section.closest( '.wp-full-overlay' ),
+ container = section.closest( '.accordion-container' ),
+ siblings = container.find( '.open' ),
+ topPanel = overlay.find( '#customize-theme-controls > ul > .accordion-section > .accordion-section-title' ).add( '#customize-info > .accordion-section-title' ),
+ backBtn = overlay.find( '.themes-panel-back' ),
+ panelTitle = section.find( '.accordion-section-title' ).first(),
+ content = section.find( '.control-panel-content' );
+
+ if ( expanded ) {
+
+ // Collapse any sibling sections/panels
+ api.section.each( function ( otherSection ) {
+ if ( otherSection !== panel ) {
+ otherSection.collapse( { duration: args.duration } );
+ }
+ });
+ api.panel.each( function ( otherPanel ) {
+ if ( panel !== otherPanel ) {
+ otherPanel.collapse( { duration: 0 } );
+ }
+ });
+
+ content.show( 0, function() {
+ position = content.offset().top;
+ scroll = container.scrollTop();
+ content.css( 'margin-top', ( 45 - position - scroll ) );
+ section.addClass( 'current-panel' );
+ overlay.addClass( 'in-themes-panel' );
+ container.scrollTop( 0 );
+ if ( args.completeCallback ) {
+ args.completeCallback();
+ }
+ } );
+ topPanel.attr( 'tabindex', '-1' );
+ backBtn.attr( 'tabindex', '0' );
+ backBtn.focus();
+ } else {
+ siblings.removeClass( 'open' );
+ section.removeClass( 'current-panel' );
+ overlay.removeClass( 'in-themes-panel' );
+ content.delay( 180 ).hide( 0, function() {
+ content.css( 'margin-top', 'inherit' ); // Reset
+ if ( args.completeCallback ) {
+ args.completeCallback();
+ }
+ } );
+ topPanel.attr( 'tabindex', '0' );
+ backBtn.attr( 'tabindex', '-1' );
+ panelTitle.focus();
+ container.scrollTop( 0 );
+ }
+ },
+
+ /**
+ * Advance the modal to the next theme.
+ *
+ * @since 4.2.0
+ */
+ nextTheme: function () {
+ var section = this;
+ if ( section.getNextTheme() ) {
+ section.showDetails( section.getNextTheme(), function() {
+ section.overlay.find( '.right' ).focus();
+ } );
+ }
+ },
+
+ /**
+ * Get the next theme model.
+ *
+ * @since 4.2.0
+ */
+ getNextTheme: function () {
+ var control, next;
+ control = api.control( 'theme_' + this.currentTheme );
+ next = control.container.next( 'li.customize-control-theme' );
+ if ( ! next.length ) {
+ return false;
+ }
+ next = next[0].id.replace( 'customize-control-', '' );
+ control = api.control( next );
+
+ return control.params.theme;
+ },
+
+ /**
+ * Advance the modal to the previous theme.
+ *
+ * @since 4.2.0
+ */
+ previousTheme: function () {
+ var section = this;
+ if ( section.getPreviousTheme() ) {
+ section.showDetails( section.getPreviousTheme(), function() {
+ section.overlay.find( '.left' ).focus();
+ } );
+ }
+ },
+
+ /**
+ * Get the previous theme model.
+ *
+ * @since 4.2.0
+ */
+ getPreviousTheme: function () {
+ var control, previous;
+ control = api.control( 'theme_' + this.currentTheme );
+ previous = control.container.prev( 'li.customize-control-theme' );
+ if ( ! previous.length ) {
+ return false;
+ }
+ previous = previous[0].id.replace( 'customize-control-', '' );
+ control = api.control( previous );
+
+ return control.params.theme;
+ },
+
+ /**
+ * Disable buttons when we're viewing the first or last theme.
+ *
+ * @since 4.2.0
+ */
+ updateLimits: function () {
+ if ( ! this.getNextTheme() ) {
+ this.overlay.find( '.right' ).addClass( 'disabled' );
+ }
+ if ( ! this.getPreviousTheme() ) {
+ this.overlay.find( '.left' ).addClass( 'disabled' );
+ }
+ },
+
+ /**
+ * Render & show the theme details for a given theme model.
+ *
+ * @since 4.2.0
+ *
+ * @param {Object} theme
+ */
+ showDetails: function ( theme, callback ) {
+ var section = this;
+ callback = callback || function(){};
+ section.currentTheme = theme.id;
+ section.overlay.html( section.template( theme ) )
+ .fadeIn( 'fast' )
+ .focus();
+ $( 'body' ).addClass( 'modal-open' );
+ section.containFocus( section.overlay );
+ section.updateLimits();
+ callback();
+ },
+
+ /**
+ * Close the theme details modal.
+ *
+ * @since 4.2.0
+ */
+ closeDetails: function ( theme ) {
+ $( 'body' ).removeClass( 'modal-open' );
+ this.overlay.fadeOut( 'fast' );
+ api.control( 'theme_' + this.currentTheme ).focus();
+ },
+
+ /**
+ * Keep tab focus within the theme details modal.
+ *
+ * @since 4.2.0
+ */
+ containFocus: function( el ) {
+ var tabbables;
+
+ el.on( 'keydown', function( event ) {
+
+ // Return if it's not the tab key
+ // When navigating with prev/next focus is already handled
+ if ( 9 !== event.keyCode ) {
+ return;
+ }
+
+ // uses jQuery UI to get the tabbable elements
+ tabbables = $( ':tabbable', el );
+
+ // Keep focus within the overlay
+ if ( tabbables.last()[0] === event.target && ! event.shiftKey ) {
+ tabbables.first().focus();
+ return false;
+ } else if ( tabbables.first()[0] === event.target && event.shiftKey ) {
+ tabbables.last().focus();
+ return false;
+ }
+ });
+ }
+ });
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * @since 4.1.0
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @class
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1409,6 +1754,63 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> });
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * wp.customize.ThemeControl
+ *
+ * @constructor
+ * @augments wp.customize.Control
+ * @augments wp.customize.Class
+ */
+ api.ThemeControl = api.Control.extend({
+
+ /**
+ * @since 4.2.0
+ */
+ ready: function() {
+ var control = this;
+
+ // Bind details view trigger.
+ control.container.on( 'click keydown', '.theme', function( event ) {
+ if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+ return;
+ }
+
+ if ( 'button' === event.target.className ) {
+ return;
+ }
+
+ api.section( control.section() ).showDetails( control.params.theme );
+ });
+
+ control.container.on( 'click keydown', '.theme-actions .button', function( event ) {
+ if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
+ return;
+ }
+
+ $( '.wp-full-overlay' ).addClass( 'customize-loading' );
+ });
+ },
+
+ /**
+ * Show or hide the theme based on the presence of the term in the title, description, and author.
+ *
+ * @since 4.2.0
+ */
+ filter: function( term ) {
+ var control = this,
+ haystack = control.params.theme.name + ' '
+ + control.params.theme.description + ' '
+ + control.params.theme.tags + ' '
+ + control.params.theme.author;
+ haystack = haystack.toLowerCase().replace( '-', ' ' );
+ if ( -1 !== haystack.search( term ) ) {
+ control.activate();
+ } else {
+ control.deactivate();
+ }
+ }
+ });
+
</ins><span class="cx" style="display: block; padding: 0 10px"> // Change objects contained within the main customize object to Settings.
</span><span class="cx" style="display: block; padding: 0 10px"> api.defaultConstructor = api.Setting;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1853,14 +2255,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> });
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> api.controlConstructor = {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- color: api.ColorControl,
- upload: api.UploadControl,
- image: api.ImageControl,
- header: api.HeaderControl,
- background: api.BackgroundControl
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ color: api.ColorControl,
+ upload: api.UploadControl,
+ image: api.ImageControl,
+ header: api.HeaderControl,
+ background: api.BackgroundControl,
+ theme: api.ThemeControl
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px"> api.panelConstructor = {};
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- api.sectionConstructor = {};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ api.sectionConstructor = {
+ themes: api.ThemesSection
+ };
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $( function() {
</span><span class="cx" style="display: block; padding: 0 10px"> api.settings = window._wpCustomizeSettings;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2273,6 +2678,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Prompt user with AYS dialog if leaving the Customizer with unsaved changes
</span><span class="cx" style="display: block; padding: 0 10px"> $( window ).on( 'beforeunload', function () {
</span><span class="cx" style="display: block; padding: 0 10px"> if ( ! api.state( 'saved' )() ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var timeout = setTimeout( function() {
+ overlay.removeClass( 'customize-loading' );
+ }, 1 );
</ins><span class="cx" style="display: block; padding: 0 10px"> return api.l10n.saveAlert;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> } );
</span></span></pre></div>
<a id="trunksrcwpincludesadminbarphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/admin-bar.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/admin-bar.php 2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-includes/admin-bar.php 2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -650,14 +650,33 @@
</span><span class="cx" style="display: block; padding: 0 10px"> function wp_admin_bar_appearance_menu( $wp_admin_bar ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_admin_bar->add_group( array( 'parent' => 'site-name', 'id' => 'appearance' ) );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( current_user_can( 'switch_themes' ) || current_user_can( 'edit_theme_options' ) )
- $wp_admin_bar->add_menu( array( 'parent' => 'appearance', 'id' => 'themes', 'title' => __('Themes'), 'href' => admin_url('themes.php') ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
+ $customize_url = add_query_arg( 'url', urlencode( $current_url ), wp_customize_url() );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( ! current_user_can( 'edit_theme_options' ) )
- return;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( current_user_can( 'switch_themes' ) ) {
+ $wp_admin_bar->add_menu( array(
+ 'parent' => 'appearance',
+ 'id' => 'themes',
+ 'title' => __( 'Themes' ),
+ 'href' => admin_url( 'themes.php' ),
+ 'meta' => array(
+ 'class' => 'hide-if-customize',
+ ),
+ ) );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
- $customize_url = add_query_arg( 'url', urlencode( $current_url ), wp_customize_url() );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( current_user_can( 'customize' ) ) {
+ $wp_admin_bar->add_menu( array(
+ 'parent' => 'appearance',
+ 'id' => 'customize-themes',
+ 'title' => __( 'Themes' ),
+ 'href' => add_query_arg( urlencode( 'autofocus[section]' ), 'themes', $customize_url ), // urlencode() needed due to #16859
+ 'meta' => array(
+ 'class' => 'hide-if-no-customize',
+ ),
+ ) );
+ }
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( current_user_can( 'customize' ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_admin_bar->add_menu( array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'parent' => 'appearance',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -671,6 +690,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> add_action( 'wp_before_admin_bar_render', 'wp_customize_support_script' );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! current_user_can( 'edit_theme_options' ) ) {
+ return;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( current_theme_supports( 'widgets' ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_admin_bar->add_menu( array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'parent' => 'appearance',
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpcustomizecontrolphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-customize-control.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-customize-control.php 2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-includes/class-wp-customize-control.php 2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1101,6 +1101,101 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Customize Theme Control Class
+ *
+ * @package WordPress
+ * @subpackage Customize
+ * @since 4.2.0
+ */
+class WP_Customize_Theme_Control extends WP_Customize_Control {
+
+ public $type = 'theme';
+ public $theme;
+
+ /**
+ * Refresh the parameters passed to the JavaScript via JSON.
+ *
+ * @since 4.2.0
+ * @uses WP_Customize_Control::to_json()
+ */
+ public function to_json() {
+ parent::to_json();
+ $this->json['theme'] = $this->theme;
+ }
+
+ /**
+ * Don't render the control content from PHP, as it's rendered via JS on load.
+ *
+ * @since 4.2.0
+ */
+ public function render_content() {}
+
+ /**
+ * Render a JS template for theme display.
+ *
+ * @since 4.2.0
+ */
+ public function content_template() {
+ ?>
+ <div class="theme<# if ( data.theme.active ) { #> active<# } #>" tabindex="0" aria-describedby="{{ data.theme.id }}-action {{ data.theme.id }}-name">
+ <# if ( data.theme.screenshot[0] ) { #>
+ <div class="theme-screenshot">
+ <img src="{{ data.theme.screenshot[0] }}" alt="" />
+ </div>
+ <# } else { #>
+ <div class="theme-screenshot blank"></div>
+ <# } #>
+ <span class="more-details" id="{{ data.theme.id }}-action"><?php _e( 'Theme Details' ); ?></span>
+ <div class="theme-author"><?php printf( __( 'By %s' ), '{{ data.theme.author }}' ); ?></div>
+
+ <# if ( data.theme.active ) { #>
+ <h3 class="theme-name" id="{{ data.theme.id }}-name"><span><?php _ex( 'Previewing:', 'theme' ); ?></span> {{ data.theme.name }}</h3>
+ <# } else { #>
+ <h3 class="theme-name" id="{{ data.theme.id }}-name">{{ data.theme.name }}</h3>
+ <# } #>
+
+ <# if ( ! data.theme.active ) { #>
+ <div class="theme-actions">
+ <a class="button" href="<?php echo add_query_arg( 'theme', '{{ data.theme.id }}', remove_query_arg( 'theme' ) ); ?>" target="_top"><?php _e( 'Live Preview' ); ?></a>
+ </div>
+ <# } #>
+ </div>
+ <?php
+ }
+}
+
+/**
+ * Customize New Theme Control Class
+ *
+ * @package WordPress
+ * @subpackage Customize
+ * @since 4.2.0
+ */
+class WP_Customize_New_Theme_Control extends WP_Customize_Control {
+
+ /**
+ * Render the new control.
+ *
+ * @since 4.2.0
+ */
+ public function render() {
+ if ( is_multisite() || ! current_user_can( 'install_themes') ) {
+ return;
+ }
+ ?>
+ <div class="theme add-new-theme">
+ <a href="<?php echo admin_url( 'theme-install.php' ); ?>" target="_top">
+ <div class="theme-screenshot">
+ <span></span>
+ </div>
+ <h3 class="theme-name"><?php _e( 'Add New Theme' ); ?></h3>
+ </a>
+ </div>
+ <?php
+ }
+}
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Widget Area Customize Control Class
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 3.9.0
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpcustomizemanagerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-customize-manager.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-customize-manager.php 2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-includes/class-wp-customize-manager.php 2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1110,7 +1110,39 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->register_control_type( 'WP_Customize_Upload_Control' );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->register_control_type( 'WP_Customize_Image_Control' );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->register_control_type( 'WP_Customize_Background_Image_Control' );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->register_control_type( 'WP_Customize_Theme_Control' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /* Themes */
+
+ $this->add_section( new WP_Customize_Themes_Section( $this, 'themes', array(
+ 'title' => sprintf( __( 'Theme: %s' ), $this->theme()->display('Name') ),
+ 'capability' => 'switch_themes',
+ 'priority' => 0,
+ ) ) );
+
+ // Themes Setting (unused - the theme is considerably more fundamental to the Customizer experience).
+ $this->add_setting( new WP_Customize_Filter_Setting( $this, 'active_theme', array(
+ 'capability' => 'switch_themes',
+ ) ) );
+
+ require_once( ABSPATH . 'wp-admin/includes/theme.php' );
+
+ // Theme Controls.
+ $themes = wp_prepare_themes_for_js();
+ foreach ( $themes as $theme ) {
+ $theme_id = 'theme_' . $theme['id'];
+ $this->add_control( new WP_Customize_Theme_Control( $this, $theme_id, array(
+ 'theme' => $theme,
+ 'section' => 'themes',
+ 'settings' => 'active_theme',
+ ) ) );
+ }
+
+ $this->add_control( new WP_Customize_New_Theme_Control( $this, 'add_theme', array(
+ 'section' => 'themes',
+ 'settings' => 'active_theme',
+ ) ) );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /* Site Title & Tagline */
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->add_section( 'title_tagline', array(
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpcustomizesectionphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-customize-section.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-customize-section.php 2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-includes/class-wp-customize-section.php 2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -312,6 +312,57 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Customize Themes Section Class.
+ *
+ * A UI container for theme controls, which behaves like a backwards Panel.
+ *
+ * @package WordPress
+ * @subpackage Customize
+ * @since 4.2.0
+ */
+class WP_Customize_Themes_Section extends WP_Customize_Section {
+
+ public $type = 'themes';
+
+ /**
+ * Render the themes section, which behaves like a panel.
+ *
+ * @since 4.2.0
+ */
+ protected function render() {
+ $classes = 'accordion-section control-section control-section-' . $this->type;
+ ?>
+ <li id="accordion-section-<?php echo esc_attr( $this->id ); ?>" class="<?php echo esc_attr( $classes ); ?>">
+ <h3 class="accordion-section-title" tabindex="0">
+ <?php echo esc_html( $this->title ); ?>
+ <span class="screen-reader-text"><?php _e( 'Press return or enter to expand' ); ?></span>
+ </h3>
+ <span class="control-panel-back themes-panel-back" tabindex="-1"><span class="screen-reader-text"><?php _e( 'Back' ); ?></span></span>
+ <div class="customize-themes-panel control-panel-content themes-php">
+ <h2><?php esc_html_e( 'Themes' ); ?>
+ <span class="title-count theme-count"><?php echo count( $this->controls ) - 1; ?></span>
+ <?php if ( ! is_multisite() && current_user_can( 'install_themes' ) ) : ?>
+ <a href="<?php echo admin_url( 'theme-install.php' ); ?>" target="_top" class="add-new-h2"><?php echo esc_html_x( 'Add New', 'Add new theme' ); ?></a>
+ <?php endif; ?>
+ </h2>
+ <div class="theme-overlay" tabindex="0" role="dialog" aria-label="<?php esc_attr_e( 'Theme details' ); ?>"></div>
+ <div id="customize-container"></div>
+ <?php if ( 6 < count( $this->controls ) ) : ?>
+ <p><label for="themes-filter">
+ <span class="screen-reader-text"><?php _e( 'Search installed themes...' ); ?></span>
+ <input type="search" id="themes-filter" placeholder="<?php esc_attr_e( 'Search installed themes...' ); ?>" />
+ </label></p>
+ <?php endif; ?>
+ <div class="theme-browser rendered">
+ <ul class="themes accordion-section-content">
+ </ul>
+ </div>
+ </div>
+ </li>
+<?php }
+}
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Customizer section representing widget area (sidebar).
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @package WordPress
</span></span></pre></div>
<a id="trunksrcwpincludesversionphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/version.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/version.php 2015-02-24 16:36:26 UTC (rev 31532)
+++ trunk/src/wp-includes/version.php 2015-02-24 20:30:22 UTC (rev 31533)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -11,7 +11,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @global int $wp_db_version
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-$wp_db_version = 31351;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+$wp_db_version = 31532;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Holds the TinyMCE version
</span></span></pre>
</div>
</div>
</body>
</html>