<!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>[27499] trunk/src: Bring the theme browsing experience from 3.8 to the theme installer.</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">
<dt>Revision</dt> <dd><a href="http://core.trac.wordpress.org/changeset/27499">27499</a></dd>
<dt>Author</dt> <dd>nacin</dd>
<dt>Date</dt> <dd>2014-03-11 07:46:27 +0000 (Tue, 11 Mar 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Bring the theme browsing experience from 3.8 to the theme installer. First pass.

props matveb with assists from me and gcorne.
see <a href="http://core.trac.wordpress.org/ticket/27055">#27055</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpadmincssthemescss">trunk/src/wp-admin/css/themes.css</a></li>
<li><a href="#trunksrcwpadminincludesthemeinstallphp">trunk/src/wp-admin/includes/theme-install.php</a></li>
<li><a href="#trunksrcwpadminjsthemejs">trunk/src/wp-admin/js/theme.js</a></li>
<li><a href="#trunksrcwpadminthemeinstallphp">trunk/src/wp-admin/theme-install.php</a></li>
<li><a href="#trunksrcwpadminupdatephp">trunk/src/wp-admin/update.php</a></li>
<li><a href="#trunksrcwpincludesscriptloaderphp">trunk/src/wp-includes/script-loader.php</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunksrcwpadminjsthemeinstalljs">trunk/src/wp-admin/js/theme-install.js</a></li>
<li><a href="#trunksrcwpadminjsthemepreviewjs">trunk/src/wp-admin/js/theme-preview.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpadmincssthemescss"></a>
<div class="modfile"><h4>Modified: trunk/src/wp-admin/css/themes.css (27498 => 27499)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-admin/css/themes.css        2014-03-11 04:19:25 UTC (rev 27498)
+++ trunk/src/wp-admin/css/themes.css   2014-03-11 07:46:27 UTC (rev 27499)
</span><span class="lines">@@ -25,7 +25,8 @@
</span><span class="cx">  margin-left: 20px;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.themes-php .wrap .theme-count {
</del><ins>+.themes-php .wrap .theme-count,
+.theme-navigation .theme-count {
</ins><span class="cx">   color: #fff;
</span><span class="cx">  -webkit-border-radius: 30px;
</span><span class="cx">  border-radius: 30px;
</span><span class="lines">@@ -1064,158 +1065,211 @@
</span><span class="cx">   16.2 - Install Themes
</span><span class="cx"> ------------------------------------------------------------------------------*/
</span><span class="cx"> 
</span><del>-.theme-install-php h4 {
-       margin: 2.5em 0 8px;
</del><ins>+.theme-install-php h2 .upload {
+       margin-left: 10px;
</ins><span class="cx"> }
</span><del>-
-.theme-install-php .tablenav {
-       height: auto;
</del><ins>+.theme-navigation {
+       background: #fff;
+       box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
+       -moz-box-sizing: border-box;
+       box-sizing: border-box;
+       color: #555;
+       display: inline-block;
+       font-size: 13px;
+       margin: 20px 0 30px;
+       padding: 0 20px;
+       position: relative;
+       width: 100%;
</ins><span class="cx"> }
</span><del>-
-.theme-install-php .spinner {
-       margin-top: 9px;
-}
-
-.available-theme {
-       display: inline-block;
-       margin-right: 10px;
</del><ins>+.upload-theme {
+       -moz-box-sizing: border-box;
+       box-sizing: border-box;
+       display: none;
+       margin: 0px 0 0;
+       padding: 0;
+       width: 100%;
</ins><span class="cx">   overflow: hidden;
</span><del>-       padding: 20px 20px 20px 0;
-       vertical-align: top;
-       width: 300px;
</del><ins>+        position: relative;
+               top: 10px;
</ins><span class="cx"> }
</span><del>-
-.available-theme .screenshot {
-       width: 300px;
-       height: 225px;
</del><ins>+.upload-theme.opened {
</ins><span class="cx">   display: block;
</span><del>-       border: 1px solid #ccc;
-       margin-bottom: 10px;
-       overflow: hidden;
-       background-color: #fff;
</del><span class="cx"> }
</span><del>-
-.available-theme img {
-       width: 300px;
</del><ins>+.upload-theme .wp-upload-form {
+       background: #fafafa;
+       border: 1px solid #e5e5e5;
+       padding: 30px;
+       margin: 30px auto;
+       max-width: 380px;
</ins><span class="cx"> }
</span><del>-
-.available-theme h3 {
-       margin: 15px 0 0;
</del><ins>+.upload-theme .install-help {
+       color: #999;
+       font-size: 18px;
+       font-style: normal;
+       margin: 0;
+       padding: 40px 0 0;
+       text-align: center;
</ins><span class="cx"> }
</span><del>-
-.available-theme .theme-author {
-       line-height: 18px;
</del><ins>+.upload-theme.opened + .theme-navigation,
+.upload-theme.opened + .theme-navigation + .theme-browser {
+       display: none;
</ins><span class="cx"> }
</span><del>-
-.available-theme .action-links {
-       margin-top: 10px;
-       overflow: hidden;
</del><ins>+.theme-navigation .theme-count {
+       top: 3px;
+       margin-left: 0;
</ins><span class="cx"> }
</span><del>-
-.available-theme a.screenshot:focus {
-       border-color: #777;
</del><ins>+.theme-section,
+.theme-filter {
+       border-bottom: 4px solid #fff;
+       color: #666;
+       cursor: pointer;
+       display: inline-block;
+       margin: 0 10px;
+       padding: 15px 0;
+       -moz-transition: border-color .1s ease-in;
+       -webkit-transition: border-color .1s ease-in;
</ins><span class="cx"> }
</span><del>-
-.available-theme .action-links li {
-       float: left;
-       padding-right: 10px;
-       margin-right: 10px;
-       border-right: 1px solid #dfdfdf;
</del><ins>+.theme-section.current,
+.theme-filter.current {
+       border-bottom: 4px solid #666;
+       color: #222;
</ins><span class="cx"> }
</span><del>-
-.available-theme .action-links li {
-       padding-right: 8px;
-       margin-right: 8px;
</del><ins>+.theme-top-filters {
+       display: inline-block;
</ins><span class="cx"> }
</span><del>-
-.ie8 .available-theme .action-links li {
-       padding-right: 7px;
-       margin-right: 7px;
</del><ins>+.theme-navigation .more-filters {
+       color: #666;
+       cursor: pointer;
+       display: inline-block;
+       margin: 0 10px;
+       padding: 4px 5px;
+       -moz-transition: color .1s ease-in, background .1s ease-in;
+       -webkit-transition: color .1s ease-in, background .1s ease-in;
+       transition: color .1s ease-in, background .1s ease-in;
</ins><span class="cx"> }
</span><del>-
-.available-theme .action-links li:last-child {
-       padding-right: 0;
-       margin-right: 0;
-       border-right: 0;
</del><ins>+body.more-filters-opened .more-filters,
+.theme-navigation .more-filters.current {
+       background: rgb(46, 162, 204);
+       border-radius: 2px;
+       border: none;
+       color: #fff;
</ins><span class="cx"> }
</span><del>-
-.available-theme .action-links .delete-theme {
-       float: right;
-       margin-left: 8px;
-       margin-right: 0;
</del><ins>+.theme-install-php .theme-search {
+       position: absolute;
+               right: 10px;
+               top: 9px;
+       font-size: 16px;
+       font-weight: 300;
+       line-height: 1.5;
+       width: 280px;
</ins><span class="cx"> }
</span><del>-
-.available-theme .action-links .delete-theme a {
-       color: red;
-       padding: 2px;
</del><ins>+.more-filters:before {
+       color: #777;
+       text-align: center;
+       margin: 0 5px 0 0;
+       content: "\f111";
+       display: inline-block;
+       width: 16px;
+       height: 16px;
+       -webkit-font-smoothing: antialiased;
+       font-size: 16px;
+       line-height: 1;
+       font-family: "dashicons";
+       text-decoration: inherit;
+       font-weight: normal;
+       font-style: normal;
+       vertical-align: top;
+       -moz-transition: color .1s ease-in 0;
+       -webkit-transition: color .1s ease-in 0;
+       transition: color .1s ease-in 0;
+       text-align: center;
</ins><span class="cx"> }
</span><del>-
-.available-theme .action-links .delete-theme a:hover {
-       background: red;
</del><ins>+.more-filters.current:before {
</ins><span class="cx">   color: #fff;
</span><del>-       text-decoration: none;
</del><span class="cx"> }
</span><del>-
-.available-theme .action-links p {
-       float: left;
</del><ins>+.more-filters-container {
+       display: none;
+       padding: 30px;
+       border-top: 1px solid #eee;
+       margin: 0 -20px;
+       background: #fafafa;
</ins><span class="cx"> }
</span><del>-
-/* Allow for three-up in small windows when sidebar is collapsed */
-@media only screen and (max-width: 1200px) {
-       .folded .available-theme,
-       .folded .available-theme .screenshot {
-               width: 300px;
-       }
-
-       .folded .available-theme .screenshot {
-               height: 225px;
-       }
</del><ins>+body.more-filters-opened .more-filters-container {
+       display: block;
</ins><span class="cx"> }
</span><del>-
-/* Adjust three-up display in smaller windows when sidebar is collapsed */
-@media only screen and (max-width: 1079px) {
-       .folded .available-theme,
-       .folded .available-theme .screenshot {
-               width: 270px;
-       }
-
-       .folded .available-theme .screenshot {
-               height: 203px;
-       }
</del><ins>+.theme-install-php .add-new-theme {
+       display: none !important;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-/* Allow for three-up on 1024px wide screens, e.g. tablets */
-@media only screen and (max-width: 1200px) {
-       .available-theme,
-       .available-theme .screenshot {
-               width: 240px;
-       }
-
-       .available-theme .screenshot {
-               height: 180px;
-       }
-
-       .available-theme img {
-               width: 100%;
-       }
</del><ins>+.rating {
+       margin: 30px 0;
</ins><span class="cx"> }
</span><del>-
-.feature-filter {
-       padding: 8px 12px 0;
-}
-
-.feature-filter .feature-group {
-       float: left;
-       margin: 5px 10px 10px;
-}
-
-.feature-filter .feature-group li {
</del><ins>+.rating span:before {
+       color: #e6b800;
+       content: "\f154";
</ins><span class="cx">   display: inline-block;
</span><ins>+       -webkit-font-smoothing: antialiased;
+       font: normal 20px/1 'dashicons';
</ins><span class="cx">   vertical-align: top;
</span><del>-       list-style-type: none;
-       padding-right: 25px;
-       width: 150px;
</del><span class="cx"> }
</span><ins>+/* Half stars */
+.rating-10 span.one:before,
+.rating-30 span.two:before,
+.rating-50 span.three:before,
+.rating-70 span.four:before,
+.rating-90 span.five:before {
+       content: "\f459";
+}
+/* Full stars */
+.rating-20 span.one:before {
+       content: "\f155";
+}
+.rating-30 span.one:before,
+.rating-40 span.one:before,
+.rating-40 span.two:before {
+       content: "\f155";
+}
+.rating-50 span.one:before,
+.rating-50 span.two:before,
+.rating-60 span.one:before,
+.rating-60 span.two:before,
+.rating-60 span.three:before {
+       content: "\f155";
+}
+.rating-70 span.one:before,
+.rating-70 span.two:before,
+.rating-70 span.three:before,
+.rating-80 span.one:before,
+.rating-80 span.two:before,
+.rating-80 span.three:before,
+.rating-80 span.four:before {
+       content: "\f155";
+}
+.rating-90 span.one:before,
+.rating-90 span.two:before,
+.rating-90 span.three:before,
+.rating-90 span.four:before,
+.rating-100 span.one:before,
+.rating-100 span.two:before,
+.rating-100 span.three:before,
+.rating-100 span.four:before,
+.rating-100 span.five:before {
+       content: "\f155";
+}
+.rating .votes {
+       display: inline;
+       margin-left: 10px;
+       line-height: 20px;
+}
+.loading-themes .theme-browser,
+.error .theme-browser {
+       display: none;
+}
+.loading-themes .spinner {
+       display: block;
+       margin: 40px auto 0;
+       float: none;
+}
</ins><span class="cx"> 
</span><span class="cx"> /*------------------------------------------------------------------------------
</span><span class="cx">   16.3 - Custom Header Screen
</span></span></pre></div>
<a id="trunksrcwpadminincludesthemeinstallphp"></a>
<div class="modfile"><h4>Modified: trunk/src/wp-admin/includes/theme-install.php (27498 => 27499)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-admin/includes/theme-install.php    2014-03-11 04:19:25 UTC (rev 27498)
+++ trunk/src/wp-admin/includes/theme-install.php       2014-03-11 07:46:27 UTC (rev 27499)
</span><span class="lines">@@ -132,11 +132,10 @@
</span><span class="cx"> </form>
</span><span class="cx"> <?php
</span><span class="cx"> }
</span><del>-add_action('install_themes_dashboard', 'install_themes_dashboard');
</del><ins>+// add_action('install_themes_dashboard', 'install_themes_dashboard');
</ins><span class="cx"> 
</span><del>-function install_themes_upload($page = 1) {
</del><ins>+function install_themes_upload() {
</ins><span class="cx"> ?>
</span><del>-<h4><?php _e('Install a theme in .zip format'); ?></h4>
</del><span class="cx"> <p class="install-help"><?php _e('If you have a theme in a .zip format, you may install it by uploading it here.'); ?></p>
</span><span class="cx"> <form method="post" enctype="multipart/form-data" class="wp-upload-form" action="<?php echo self_admin_url('update.php?action=upload-theme'); ?>">
</span><span class="cx">  <?php wp_nonce_field( 'theme-upload'); ?>
</span><span class="lines">@@ -145,7 +144,7 @@
</span><span class="cx"> </form>
</span><span class="cx">  <?php
</span><span class="cx"> }
</span><del>-add_action('install_themes_upload', 'install_themes_upload', 10, 1);
</del><ins>+// add_action('install_themes_upload', 'install_themes_upload', 10, 0);
</ins><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * Prints a theme on the Install Themes pages.
</span><span class="lines">@@ -155,6 +154,10 @@
</span><span class="cx"> function display_theme( $theme ) {
</span><span class="cx">  _deprecated_function( __FUNCTION__, '3.4' );
</span><span class="cx">  global $wp_list_table;
</span><ins>+       if ( ! isset( $wp_list_table ) ) {
+               $wp_list_table = _get_list_table('WP_Theme_Install_List_Table');
+       }
+       $wp_list_table->prepare_items();
</ins><span class="cx">   $wp_list_table->single_row( $theme );
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -166,12 +169,17 @@
</span><span class="cx"> function display_themes() {
</span><span class="cx">  global $wp_list_table;
</span><span class="cx"> 
</span><ins>+       if ( ! isset( $wp_list_table ) ) {
+               $wp_list_table = _get_list_table('WP_Theme_Install_List_Table');
+       }
+       $wp_list_table->prepare_items();
</ins><span class="cx">   $wp_list_table->display();
</span><ins>+
</ins><span class="cx"> }
</span><del>-add_action('install_themes_search', 'display_themes');
-add_action('install_themes_featured', 'display_themes');
-add_action('install_themes_new', 'display_themes');
-add_action('install_themes_updated', 'display_themes');
</del><ins>+// add_action('install_themes_search', 'display_themes');
+// add_action('install_themes_featured', 'display_themes');
+// add_action('install_themes_new', 'display_themes');
+// add_action('install_themes_updated', 'display_themes');
</ins><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * Display theme information in dialog box form.
</span><span class="lines">@@ -179,7 +187,7 @@
</span><span class="cx">  * @since 2.8.0
</span><span class="cx">  */
</span><span class="cx"> function install_theme_information() {
</span><del>-       global $tab, $themes_allowedtags, $wp_list_table;
</del><ins>+        global $wp_list_table;
</ins><span class="cx"> 
</span><span class="cx">  $theme = themes_api( 'theme_information', array( 'slug' => wp_unslash( $_REQUEST['theme'] ) ) );
</span><span class="cx"> 
</span><span class="lines">@@ -187,6 +195,9 @@
</span><span class="cx">          wp_die( $theme );
</span><span class="cx"> 
</span><span class="cx">  iframe_header( __('Theme Install') );
</span><ins>+       if ( ! isset( $wp_list_table ) ) {
+               $wp_list_table = _get_list_table('WP_Theme_Install_List_Table');
+       }
</ins><span class="cx">   $wp_list_table->theme_installer_single( $theme );
</span><span class="cx">  iframe_footer();
</span><span class="cx">  exit;
</span></span></pre></div>
<a id="trunksrcwpadminjsthemeinstalljs"></a>
<div class="delfile"><h4>Deleted: trunk/src/wp-admin/js/theme-install.js (27498 => 27499)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-admin/js/theme-install.js   2014-03-11 04:19:25 UTC (rev 27498)
+++ trunk/src/wp-admin/js/theme-install.js      2014-03-11 07:46:27 UTC (rev 27499)
</span><span class="lines">@@ -1,268 +0,0 @@
</span><del>-/* global ajaxurl, list_args, theme_list_args */
-
-var theme_viewer;
-
-/**
- * Theme Browsing
- *
- * Controls visibility of theme details on manage and install themes pages.
- */
-jQuery( function($) {
-       $('#availablethemes').on( 'click', '.theme-detail', function (event) {
-               var theme   = $(this).closest('.available-theme'),
-                       details = theme.find('.themedetaildiv');
-
-               if ( ! details.length ) {
-                       details = theme.find('.install-theme-info .theme-details');
-                       details = details.clone().addClass('themedetaildiv').appendTo( theme ).hide();
-               }
-
-               details.toggle();
-               event.preventDefault();
-       });
-});
-
-/**
- * Theme Install
- *
- * Displays theme previews on theme install pages.
- */
-jQuery( function($) {
-       if ( ! window.postMessage ) {
-               return;
-       }
-
-       var preview = $('#theme-installer'),
-               header  = preview.find('.wp-full-overlay-header'),
-               info    = preview.find('.install-theme-info'),
-               panel   = preview.find('.wp-full-overlay-main'),
-               body    = $( document.body );
-
-       preview.on( 'click', '.close-full-overlay', function( event ) {
-               preview.fadeOut( 200, function() {
-                       panel.empty();
-                       body.removeClass('theme-installer-active full-overlay-active');
-               });
-               event.preventDefault();
-       });
-
-       preview.on( 'click', '.collapse-sidebar', function( event ) {
-               preview.toggleClass( 'collapsed' ).toggleClass( 'expanded' );
-               event.preventDefault();
-       });
-
-       $('#availablethemes').on( 'click', '.install-theme-preview', function( event ) {
-               var src;
-
-               info.html( $(this).closest('.installable-theme').find('.install-theme-info').html() );
-
-               header.find( '.theme-install' ).replaceWith( info.find( '.theme-install' ) );
-
-               src = info.find( '.theme-preview-url' ).val();
-               panel.html( '<iframe src="' + src + '" />');
-               preview.fadeIn( 200, function() {
-                       body.addClass('theme-installer-active full-overlay-active');
-               });
-               event.preventDefault();
-       });
-});
-
-var ThemeViewer;
-
-(function($){
-       ThemeViewer = function() {
-
-               function init() {
-                       $( '#filter-click, #mini-filter-click' ).unbind( 'click' ).click( function() {
-                               $( '#filter-click' ).toggleClass( 'current' );
-                               $( '#filter-box' ).slideToggle();
-                               $( '#current-theme' ).slideToggle( 300 );
-                               return false;
-                       });
-
-                       $( '#filter-box :checkbox' ).unbind( 'click' ).click( function() {
-                               var count = $( '#filter-box :checked' ).length,
-                                       text  = $( '#filter-click' ).text();
-
-                               if ( text.indexOf( '(' ) !== -1 ) {
-                                       text = text.substr( 0, text.indexOf( '(' ) );
-                               }
-
-                               if ( count === 0 ) {
-                                       $( '#filter-click' ).text( text );
-                               } else {
-                                       $( '#filter-click' ).text( text + ' (' + count + ')' );
-                               }
-                       });
-
-                       /* $('#filter-box :submit').unbind( 'click' ).click(function() {
-                               var features = [];
-                               $('#filter-box :checked').each(function() {
-                                       features.push($(this).val());
-                               });
-
-                               listTable.update_rows({'features': features}, true, function() {
-                                       $( '#filter-click' ).toggleClass( 'current' );
-                                       $( '#filter-box' ).slideToggle();
-                                       $( '#current-theme' ).slideToggle( 300 );
-                               });
-
-                               return false;
-                       }); */
-               }
-
-               // These are the functions we expose
-               var api = {
-                       init: init
-               };
-
-               return api;
-       };
-})(jQuery);
-
-jQuery( document ).ready( function() {
-       theme_viewer = new ThemeViewer();
-       theme_viewer.init();
-});
-
-
-/**
- * Class that provides infinite scroll for Themes admin screens
- *
- * @since 3.4.0
- *
- * @uses ajaxurl
- * @uses list_args
- * @uses theme_list_args
- * @uses $('#_ajax_fetch_list_nonce').val()
-* */
-var ThemeScroller;
-(function($){
-       ThemeScroller = {
-               querying: false,
-               scrollPollingDelay: 500,
-               failedRetryDelay: 4000,
-               outListBottomThreshold: 300,
-
-               /**
-                * Initializer
-                *
-                * @since 3.4.0
-                * @access private
-                */
-               init: function() {
-                       var self = this;
-
-                       // Get out early if we don't have the required arguments.
-                       if ( typeof ajaxurl === 'undefined' ||
-                               typeof list_args === 'undefined' ||
-                               typeof theme_list_args === 'undefined' ) {
-
-                               $('.pagination-links').show();
-                                       return;
-                       }
-
-                       // Handle inputs
-                       this.nonce = $('#_ajax_fetch_list_nonce').val();
-                       this.nextPage = ( theme_list_args.paged + 1 );
-
-                       // Cache jQuery selectors
-                       this.$outList = $('#availablethemes');
-                       this.$spinner = $('div.tablenav.bottom').children( '.spinner' );
-                       this.$window = $(window);
-                       this.$document = $(document);
-
-                       /**
-                        * If there are more pages to query, then start polling to track
-                        * when user hits the bottom of the current page
-                        */
-                       if ( theme_list_args.total_pages >= this.nextPage ) {
-                               this.pollInterval = setInterval( function() {
-                                       return self.poll();
-                               }, this.scrollPollingDelay );
-                       }
-               },
-
-               /**
-                * Checks to see if user has scrolled to bottom of page.
-                * If so, requests another page of content from self.ajax().
-                *
-                * @since 3.4.0
-                * @access private
-                */
-               poll: function() {
-                       var bottom = this.$document.scrollTop() + this.$window.innerHeight();
-
-                       if ( this.querying ||
-                               ( bottom < this.$outList.height() - this.outListBottomThreshold ) ) {
-                               return;
-                       }
-
-                       this.ajax();
-               },
-
-               /**
-                * Applies results passed from this.ajax() to $outList
-                *
-                * @since 3.4.0
-                * @access private
-                *
-                * @param results Array with results from this.ajax() query.
-                */
-               process: function( results ) {
-                       if ( results === undefined ) {
-                               clearInterval( this.pollInterval );
-                               return;
-                       }
-
-                       if ( this.nextPage > theme_list_args.total_pages ) {
-                               clearInterval( this.pollInterval );
-                       }
-
-                       if ( this.nextPage <= ( theme_list_args.total_pages + 1 ) ) {
-                               this.$outList.append( results.rows );
-                       }
-               },
-
-               /**
-                * Queries next page of themes
-                *
-                * @since 3.4.0
-                * @access private
-                */
-               ajax: function() {
-                       var self = this,
-                               query = {
-                               action: 'fetch-list',
-                               paged: this.nextPage,
-                               s: theme_list_args.search,
-                               tab: theme_list_args.tab,
-                               type: theme_list_args.type,
-                               _ajax_fetch_list_nonce: this.nonce,
-                               'features[]': theme_list_args.features,
-                               'list_args': list_args
-                       };
-
-                       this.querying = true;
-
-                       this.$spinner.show();
-                       $.getJSON( ajaxurl, query )
-                               .done( function( response ) {
-                                       self.nextPage++;
-                                       self.process( response );
-                                       self.$spinner.hide();
-                                       self.querying = false;
-                               })
-                               .fail( function() {
-                                       self.$spinner.hide();
-                                       self.querying = false;
-                                       setTimeout( function() { self.ajax(); }, self.failedRetryDelay );
-                               });
-               }
-       };
-
-       $(document).ready( function() {
-               ThemeScroller.init();
-       });
-
-})(jQuery);
</del></span></pre></div>
<a id="trunksrcwpadminjsthemepreviewjs"></a>
<div class="delfile"><h4>Deleted: trunk/src/wp-admin/js/theme-preview.js (27498 => 27499)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-admin/js/theme-preview.js   2014-03-11 04:19:25 UTC (rev 27498)
+++ trunk/src/wp-admin/js/theme-preview.js      2014-03-11 07:46:27 UTC (rev 27499)
</span><span class="lines">@@ -1,59 +0,0 @@
</span><del>-/* global tb_click */
-var thickDims, tbWidth, tbHeight;
-jQuery(document).ready(function($) {
-
-       thickDims = function() {
-               var tbWindow = $('#TB_window'), H = $(window).height(), W = $(window).width(), w, h;
-
-               w = (tbWidth && tbWidth < W - 90) ? tbWidth : W - 90;
-               h = (tbHeight && tbHeight < H - 60) ? tbHeight : H - 60;
-
-               if ( tbWindow.size() ) {
-                       tbWindow.width(w).height(h);
-                       $('#TB_iframeContent').width(w).height(h - 27);
-                       tbWindow.css({'margin-left': '-' + parseInt((w / 2),10) + 'px'});
-                       if ( typeof document.body.style.maxWidth !== 'undefined' ) {
-                               tbWindow.css({'top':'30px','margin-top':'0'});
-                       }
-               }
-       };
-
-       thickDims();
-       $(window).resize( function() { thickDims(); } );
-
-       $('a.thickbox-preview').click( function() {
-               tb_click.call(this);
-
-               var alink = $(this).parents('.available-theme').find('.activatelink'), link = '', href = $(this).attr('href'), url, text;
-
-               if ( tbWidth = href.match(/&tbWidth=[0-9]+/) ) {
-                       tbWidth = parseInt(tbWidth[0].replace(/[^0-9]+/g, ''), 10);
-               } else {
-                       tbWidth = $(window).width() - 90;
-               }
-
-               if ( tbHeight = href.match(/&tbHeight=[0-9]+/) ) {
-                       tbHeight = parseInt(tbHeight[0].replace(/[^0-9]+/g, ''), 10);
-               } else {
-                       tbHeight = $(window).height() - 60;
-               }
-
-               if ( alink.length ) {
-                       url = alink.attr('href') || '';
-                       text = alink.attr('title') || '';
-                       link = '&nbsp; <a href="' + url + '" target="_top" class="tb-theme-preview-link">' + text + '</a>';
-               } else {
-                       text = $(this).attr('title') || '';
-                       link = '&nbsp; <span class="tb-theme-preview-link">' + text + '</span>';
-               }
-
-               $('#TB_title').css({'background-color':'#222','color':'#dfdfdf'});
-               $('#TB_closeAjaxWindow').css({'float':'left'});
-               $('#TB_ajaxWindowTitle').css({'float':'right'}).html(link);
-
-               $('#TB_iframeContent').width('100%');
-               thickDims();
-
-               return false;
-       } );
-});
</del></span></pre></div>
<a id="trunksrcwpadminjsthemejs"></a>
<div class="modfile"><h4>Modified: trunk/src/wp-admin/js/theme.js (27498 => 27499)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-admin/js/theme.js   2014-03-11 04:19:25 UTC (rev 27498)
+++ trunk/src/wp-admin/js/theme.js      2014-03-11 07:46:27 UTC (rev 27499)
</span><span class="lines">@@ -12,11 +12,46 @@
</span><span class="cx"> themes.data = _wpThemeSettings;
</span><span class="cx"> l10n = themes.data.l10n;
</span><span class="cx"> 
</span><ins>+// Shortcut for isInstall check
+themes.isInstall = !! themes.data.settings.isInstall;
+
</ins><span class="cx"> // Setup app structure
</span><span class="cx"> _.extend( themes, { model: {}, view: {}, routes: {}, router: {}, template: wp.template });
</span><span class="cx"> 
</span><del>-themes.model = Backbone.Model.extend({});
</del><ins>+themes.Model = Backbone.Model.extend({
+       // Adds attributes to the default data coming through the .org themes api
+       // Map `id` to `slug` for shared code
+       initialize: function() {
+               var install, preview;
</ins><span class="cx"> 
</span><ins>+               // Install url for the theme
+               // using the install nonce
+               install = {
+                       action: 'install-theme',
+                       theme: this.get( 'slug' ),
+                       _wpnonce: themes.data.settings._nonceInstall
+               };
+
+               // Build the url query
+               install = themes.data.settings.updateURI + '?' + $.param( install );
+
+               // Preview url for the theme
+               preview = {
+                       tab: 'theme-information',
+                       theme: this.get( 'slug' )
+               };
+
+               preview = themes.data.settings.installURI + '?' + $.param( preview );
+
+               // Set the attributes
+               this.set({
+                       installURI: install,
+                       previewURI: preview,
+                       id: this.get( 'slug' )
+               });
+       }
+});
+
</ins><span class="cx"> // Main view controller for themes.php
</span><span class="cx"> // Unifies and renders all available views
</span><span class="cx"> themes.view.Appearance = wp.Backbone.View.extend({
</span><span class="lines">@@ -28,10 +63,11 @@
</span><span class="cx">  page: 0,
</span><span class="cx"> 
</span><span class="cx">  // Sets up a throttler for binding to 'scroll'
</span><del>-       initialize: function() {
</del><ins>+        initialize: function( options ) {
</ins><span class="cx">           // Scroller checks how far the scroll position is
</span><span class="cx">          _.bindAll( this, 'scroller' );
</span><span class="cx"> 
</span><ins>+               this.SearchView = options.SearchView ? options.SearchView : themes.view.Search;
</ins><span class="cx">           // Bind to the scroll event and throttle
</span><span class="cx">          // the results from this.scroller
</span><span class="cx">          this.window.bind( 'scroll', _.throttle( this.scroller, 300 ) );
</span><span class="lines">@@ -55,6 +91,9 @@
</span><span class="cx">          this.$el.append( '<br class="clear"/>' );
</span><span class="cx">  },
</span><span class="cx"> 
</span><ins>+       // Defines search element container
+       searchContainer: $( '#wpbody h2:first' ),
+
</ins><span class="cx">   // Search input and view
</span><span class="cx">  // for current theme collection
</span><span class="cx">  search: function() {
</span><span class="lines">@@ -66,11 +105,14 @@
</span><span class="cx">                  return;
</span><span class="cx">          }
</span><span class="cx"> 
</span><del>-               view = new themes.view.Search({ collection: self.collection, parent: this });
</del><ins>+                view = new this.SearchView({
+                       collection: self.collection,
+                       parent: this
+               });
</ins><span class="cx"> 
</span><span class="cx">          // Render and append after screen title
</span><span class="cx">          view.render();
</span><del>-               $('#wpbody h2:first')
</del><ins>+                this.searchContainer
</ins><span class="cx">                   .append( $.parseHTML( '<label class="screen-reader-text" for="theme-search-input">' + l10n.search + '</label>' ) )
</span><span class="cx">                  .append( view.el );
</span><span class="cx">  },
</span><span class="lines">@@ -95,7 +137,7 @@
</span><span class="cx"> // @has 'id' 'name' 'screenshot' 'author' 'authorURI' 'version' 'active' ...
</span><span class="cx"> themes.Collection = Backbone.Collection.extend({
</span><span class="cx"> 
</span><del>-       model: themes.model,
</del><ins>+        model: themes.Model,
</ins><span class="cx"> 
</span><span class="cx">  // Search terms
</span><span class="cx">  terms: '',
</span><span class="lines">@@ -187,9 +229,10 @@
</span><span class="cx">  html: themes.template( 'theme' ),
</span><span class="cx"> 
</span><span class="cx">  events: {
</span><del>-               'click': 'expand',
-               'keydown': 'expand',
-               'touchend': 'expand',
</del><ins>+                'click': themes.isInstall ? 'preview': 'expand',
+               'click .preview': 'preview',
+               'keydown': themes.isInstall ? 'preview': 'expand',
+               'touchend': themes.isInstall ? 'preview': 'expand',
</ins><span class="cx">           'touchmove': 'preventExpand'
</span><span class="cx">  },
</span><span class="cx"> 
</span><span class="lines">@@ -250,6 +293,24 @@
</span><span class="cx"> 
</span><span class="cx">  preventExpand: function() {
</span><span class="cx">          this.touchDrag = true;
</span><ins>+       },
+
+       preview: function( event ) {
+               // Bail if the user scrolled on a touch device
+               if ( this.touchDrag === true ) {
+                       return this.touchDrag = false;
+               }
+
+               event.preventDefault();
+
+               event = event || window.event;
+
+               var preview = new themes.view.Preview({
+                       model: this.model
+               });
+
+               preview.render();
+               $( 'div.wrap' ).append( preview.el );
</ins><span class="cx">   }
</span><span class="cx"> });
</span><span class="cx"> 
</span><span class="lines">@@ -415,6 +476,47 @@
</span><span class="cx">  }
</span><span class="cx"> });
</span><span class="cx"> 
</span><ins>+// Theme Preview view
+// Set ups a modal overlay with the expanded theme data
+themes.view.Preview = wp.Backbone.View.extend({
+
+       className: 'wp-full-overlay expanded',
+       el: '#theme-installer',
+
+       events: {
+               'click .close-full-overlay': 'close',
+               'click .collapse-sidebar': 'collapse'
+       },
+
+       // The HTML template for the theme preview
+       html: themes.template( 'theme-preview' ),
+
+       render: function() {
+               var data = this.model.toJSON();
+               this.$el.html( this.html( data ) );
+
+               themes.router.navigate( themes.router.baseUrl( '?theme=' + this.model.get( 'id' ) ), { replace: true } );
+
+               this.$el.fadeIn( 200, function() {
+                       $( 'body' ).addClass( 'theme-installer-active full-overlay-active' );
+               });
+       },
+
+       close: function() {
+               this.$el.fadeOut( 200, function() {
+                       $( 'body' ).removeClass( 'theme-installer-active full-overlay-active' );
+               });
+
+               themes.router.navigate( themes.router.baseUrl( '' ) );
+               return false;
+       },
+
+       collapse: function() {
+               this.$el.toggleClass( 'collapsed' ).toggleClass( 'expanded' );
+               return false;
+       }
+});
+
</ins><span class="cx"> // Controls the rendering of div.themes,
</span><span class="cx"> // a wrapper that will hold all the theme elements
</span><span class="cx"> themes.view.Themes = wp.Backbone.View.extend({
</span><span class="lines">@@ -732,7 +834,7 @@
</span><span class="cx"> 
</span><span class="cx"> // Sets up the routes events for relevant url queries
</span><span class="cx"> // Listens to [theme] and [search] params
</span><del>-themes.routes = Backbone.Router.extend({
</del><ins>+themes.Router = Backbone.Router.extend({
</ins><span class="cx"> 
</span><span class="cx">  routes: {
</span><span class="cx">          'themes.php?theme=:slug': 'theme',
</span><span class="lines">@@ -788,7 +890,7 @@
</span><span class="cx">          var self = this;
</span><span class="cx">          // Bind to our global thx object
</span><span class="cx">          // so that the object is available to sub-views
</span><del>-               themes.router = new themes.routes();
</del><ins>+                themes.router = new themes.Router();
</ins><span class="cx"> 
</span><span class="cx">          // Handles theme details route event
</span><span class="cx">          themes.router.on( 'route:theme', function( slug ) {
</span><span class="lines">@@ -805,17 +907,335 @@
</span><span class="cx">                  self.view.trigger( 'theme:close' );
</span><span class="cx">                  self.themes.doSearch( query );
</span><span class="cx">          });
</span><ins>+
+               this.extraRoutes();
+       },
+
+       extraRoutes: function() {
+               return false;
</ins><span class="cx">   }
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-// Ready...
-jQuery( document ).ready(
</del><ins>+// Extend the main Search view
+themes.view.InstallerSearch =  themes.view.Search.extend({
</ins><span class="cx"> 
</span><del>-       // Bring on the themes
-       _.bind( themes.Run.init, themes.Run )
</del><ins>+        events: {
+               'keyup': 'search'
+       },
</ins><span class="cx"> 
</span><del>-);
</del><ins>+        // Handles Ajax request for searching through themes in public repo
+       search: function( event ) {
+               this.collection = this.options.parent.view.collection;
</ins><span class="cx"> 
</span><ins>+               // Clear on escape.
+               if ( event.type === 'keyup' && event.which === 27 ) {
+                       event.target.value = '';
+               }
+
+               _.debounce( _.bind( this.doSearch, this ), 300 )( event.target.value );
+       },
+
+       doSearch: function( value ) {
+               var request = {},
+                       self = this;
+
+               request.search = value;
+
+               // Intercept an [author] search.
+               //
+               // If input value starts with `author:` send a request
+               // for `author` instead of a regular `search`
+               if ( value.substring( 0, 7 ) === 'author:' ) {
+                       request.search = '';
+                       request.author = value.slice( 7 );
+               }
+
+               // Intercept a [tag] search.
+               //
+               // If input value starts with `tag:` send a request
+               // for `tag` instead of a regular `search`
+               if ( value.substring( 0, 4 ) === 'tag:' ) {
+                       request.search = '';
+                       request.tag = [ value.slice( 4 ) ];
+               }
+
+               // Send Ajax POST request to api.wordpress.org/themes
+               themes.view.Installer.prototype.apiCall( request ).done( function( data ) {
+                               // Update the collection with the queried data
+                               self.collection.reset( data.themes );
+                               // Trigger a collection refresh event to render the views
+                               self.collection.trigger( 'update' );
+
+                               // Un-spin it
+                               $( 'body' ).removeClass( 'loading-themes' );
+                               $( '.theme-browser' ).find( 'div.error' ).remove();
+               }).fail( function() {
+                               $( '.theme-browser' ).find( 'div.error' ).remove();
+                               $( '.theme-browser' ).append( '<div class="error"><p>' + l10n.error + '</p></div>' );
+               });
+
+               return false;
+       }
+});
+
+themes.view.Installer = themes.view.Appearance.extend({
+
+       el: '#wpbody-content .wrap',
+
+       // Register events for sorting and filters in theme-navigation
+       events: {
+               'click .theme-section': 'onSort',
+               'click .theme-filter': 'onFilter',
+               'click .more-filters': 'moreFilters'
+       },
+
+       // Send Ajax POST request to api.wordpress.org/themes
+       apiCall: function( request ) {
+               return $.ajax({
+                       url: 'https://api.wordpress.org/themes/info/1.1/?action=query_themes',
+
+                       // We want JSON data
+                       dataType: 'json',
+                       type: 'POST',
+                       crossDomain: true,
+
+                       // Request data
+                       data: {
+                               action: 'query_themes',
+                               request: _.extend({
+                                       per_page: 36,
+                                       fields: {
+                                               description: true,
+                                               tested: true,
+                                               requires: true,
+                                               rating: true,
+                                               downloaded: true,
+                                               downloadLink: true,
+                                               last_updated: true,
+                                               homepage: true,
+                                               num_ratings: true
+                                       }
+                               }, request)
+                       },
+
+                       beforeSend: function() {
+                               // Spin it
+                               $( 'body' ).addClass( 'loading-themes' );
+                       }
+               });
+       },
+
+       // Handles all the rendering of the public theme directory
+       browse: function( section ) {
+               var self = this;
+
+               // @todo Cache the collection after fetching based on the section
+               this.collection = new themes.Collection();
+
+               // Create a new collection with the proper theme data
+               // for each section
+               this.apiCall({ browse: section }).done( function( data ) {
+                       // Update the collection with the queried data
+                       self.collection.reset( data.themes );
+                       // Trigger a collection refresh event to render the views
+                       self.collection.trigger( 'update' );
+
+                       // Un-spin it
+                       $( 'body' ).removeClass( 'loading-themes' );
+                       $( '.theme-browser' ).find( 'div.error' ).remove();
+               });
+
+               if ( this.view ) {
+                       this.view.remove();
+               }
+
+               // Set ups the view and passes the section argument
+               this.view = new themes.view.Themes({
+                       collection: this.collection,
+                       section: section,
+                       parent: this
+               });
+
+               // Reset pagination every time the install view handler is run
+               this.page = 0;
+
+               // Render and append
+               this.$el.find( '.themes' ).remove();
+               this.view.render();
+               this.$el.find( '.theme-browser' ).append( this.view.el ).addClass( 'rendered' );
+       },
+
+       // Initial render method
+       render: function() {
+               this.search();
+               this.uploader();
+               return this.browse( this.options.section );
+       },
+
+       // Sorting navigation
+       onSort: function( event ) {
+               var $el = $( event.target ),
+                       sort = $el.data( 'sort' );
+
+               // Bail if this is already active
+               if ( $el.hasClass( this.activeClass ) ) {
+                       return;
+               }
+
+               this.sort( sort );
+
+               // Trigger a router.naviagte update
+               themes.router.navigate( themes.router.baseUrl( '?sort=' + sort ) );
+       },
+
+       sort: function( sort ) {
+               $( '#theme-search-input' ).val( '' );
+
+               $( '.theme-section, .theme-filter' ).removeClass( this.activeClass );
+               $( '[data-sort="' + sort + '"]' ).addClass( this.activeClass );
+
+               this.browse( sort );
+       },
+
+       // Filters and Tags
+       onFilter: function( event ) {
+               var request,
+                       $el = $( event.target ),
+                       filter = $el.data( 'filter' ),
+                       self = this;
+
+               // Bail if this is already active
+               if ( $el.hasClass( this.activeClass ) ) {
+                       return;
+               }
+
+               $( '.theme-filter, .theme-section' ).removeClass( this.activeClass );
+               $el.addClass( this.activeClass );
+
+               if ( ! filter ) {
+                       return;
+               }
+
+               // Construct the filter request
+               // using the default values
+
+               // @todo Cache the collection after fetching based on the filter
+               request = { tag: [ filter ] };
+
+               // Send Ajax POST request to api.wordpress.org/themes
+               this.apiCall( request ).done( function( data ) {
+                               // Update the collection with the queried data
+                               self.collection.reset( data.themes );
+                               // Trigger a collection refresh event to render the views
+                               self.collection.trigger( 'update' );
+
+                               // Un-spin it
+                               $( 'body' ).removeClass( 'loading-themes' );
+                               $( '.theme-browser' ).find( 'div.error' ).remove();
+               }).fail( function() {
+                               $( '.theme-browser' ).find( 'div.error' ).remove();
+                               $( '.theme-browser' ).append( '<div class="error"><p>' + l10n.error + '</p></div>' );
+               });
+
+               return false;
+       },
+
+       activeClass: 'current',
+
+       // Overwrite search container class to append search
+       // in new location
+       searchContainer: $( '.theme-navigation' ),
+
+       uploader: function() {
+               $( 'a.upload.button' ).on( 'click', function() {
+                       $( '.upload-theme' )
+                               .toggleClass( 'opened' )
+                               .hasClass( 'opened' ) ? $( this ).text( l10n.back ) : $( this ).text( l10n.upload );
+               });
+       },
+
+       moreFilters: function() {
+               $( 'body' ).toggleClass( 'more-filters-opened' );
+       }
+});
+
+themes.InstallerRouter = Backbone.Router.extend({
+       routes: {
+               'theme-install.php?theme=:slug': 'preview',
+               'theme-install.php(?sort=:sort)': 'sort',
+               '': 'sort'
+       },
+
+       baseUrl: function( url ) {
+               return 'theme-install.php' + url;
+       }
+});
+
+
+themes.RunInstaller = {
+
+       init: function() {
+               // Set up the view
+               // Passes the default 'section' as an option
+               this.view = new themes.view.Installer({
+                       section: 'featured',
+                       SearchView: themes.view.InstallerSearch
+               });
+
+               // Render results
+               this.render();
+
+       },
+
+       render: function() {
+
+               // Render results
+               this.view.render();
+               this.routes();
+
+               Backbone.history.start({
+                       root: themes.data.settings.adminUrl,
+                       pushState: true,
+                       hashChange: false
+               });
+       },
+
+       routes: function() {
+               var self = this;
+               // Bind to our global thx object
+               // so that the object is available to sub-views
+               themes.router = new themes.InstallerRouter();
+
+               // Handles theme details route event
+               themes.router.on( 'route:theme', function( slug ) {
+                       self.view.view.expand( slug );
+               });
+
+               themes.router.on( 'route:sort', function( sort ) {
+                       if ( ! sort ) {
+                               sort = 'featured';
+                       }
+                       self.view.sort( sort );
+                       self.view.trigger( 'theme:close' );
+               });
+
+               this.extraRoutes();
+       },
+
+       extraRoutes: function() {
+               return false;
+       }
+};
+
+// Ready...
+$( document ).ready(function() {
+       if ( themes.isInstall ) {
+               themes.RunInstaller.init();
+       } else {
+               themes.Run.init();
+       }
+});
+
</ins><span class="cx"> })( jQuery );
</span><span class="cx"> 
</span><span class="cx"> // Align theme browser thickbox
</span></span></pre></div>
<a id="trunksrcwpadminthemeinstallphp"></a>
<div class="modfile"><h4>Modified: trunk/src/wp-admin/theme-install.php (27498 => 27499)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-admin/theme-install.php     2014-03-11 04:19:25 UTC (rev 27498)
+++ trunk/src/wp-admin/theme-install.php        2014-03-11 07:46:27 UTC (rev 27499)
</span><span class="lines">@@ -6,12 +6,12 @@
</span><span class="cx">  * @subpackage Administration
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-if ( !defined( 'IFRAME_REQUEST' ) && isset( $_GET['tab'] ) && ( 'theme-information' == $_GET['tab'] ) )
-       define( 'IFRAME_REQUEST', true );
-
</del><span class="cx"> /** WordPress Administration Bootstrap */
</span><span class="cx"> require_once( dirname( __FILE__ ) . '/admin.php' );
</span><ins>+require( ABSPATH . 'wp-admin/includes/theme-install.php' );
</ins><span class="cx"> 
</span><ins>+wp_reset_vars( array( 'tab' ) );
+
</ins><span class="cx"> if ( ! current_user_can('install_themes') )
</span><span class="cx">  wp_die( __( 'You do not have sufficient permissions to install themes on this site.' ) );
</span><span class="cx"> 
</span><span class="lines">@@ -20,20 +20,44 @@
</span><span class="cx">  exit();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-$wp_list_table = _get_list_table('WP_Theme_Install_List_Table');
-$pagenum = $wp_list_table->get_pagenum();
-$wp_list_table->prepare_items();
</del><ins>+$title = __( 'Add Themes' );
+$parent_file = 'themes.php';
</ins><span class="cx"> 
</span><del>-$title = __('Install Themes');
-$parent_file = 'themes.php';
-if ( !is_network_admin() )
</del><ins>+if ( ! is_network_admin() ) {
</ins><span class="cx">   $submenu_file = 'themes.php';
</span><ins>+}
</ins><span class="cx"> 
</span><del>-wp_enqueue_script( 'theme-install' );
-wp_enqueue_script( 'theme-preview' );
</del><ins>+$sections = array(
+       'featured' => __( 'Featured Themes' ),
+       'popular'  => __( 'Popular Themes' ),
+       'new'      => __( 'Newest Themes' ),
+);
</ins><span class="cx"> 
</span><del>-$body_id = $tab;
</del><ins>+wp_localize_script( 'theme', '_wpThemeSettings', array(
+       'themes'   => false,
+       'settings' => array(
+               'isInstall'     => true,
+               'canInstall'    => current_user_can( 'install_themes' ),
+               'installURI'    => current_user_can( 'install_themes' ) ? self_admin_url( 'theme-install.php' ) : null,
+               'adminUrl'      => parse_url( self_admin_url(), PHP_URL_PATH ),
+               'updateURI'     => self_admin_url( 'update.php' ),
+               '_nonceInstall' => wp_create_nonce( 'install-theme' )
+       ),
+       'l10n' => array(
+               'addNew' => __( 'Add New Theme' ),
+               'search'  => __( 'Search Themes' ),
+               'searchPlaceholder' => __( 'Search themes...' ),
+               'upload' => __( 'Upload Theme' ),
+               'back'   => __( 'Back' ),
+               'error'  => __( 'There was a problem trying to load the themes. Please, try again.' ),
+       ),
+       'browse' => array(
+               'sections' => $sections,
+       ),
+) );
</ins><span class="cx"> 
</span><ins>+wp_enqueue_script( 'theme' );
+
</ins><span class="cx"> /**
</span><span class="cx">  * Fires before each of the tabs are rendered on the Install Themes page.
</span><span class="cx">  *
</span><span class="lines">@@ -43,7 +67,9 @@
</span><span class="cx">  *
</span><span class="cx">  * @since 2.8.0
</span><span class="cx">  */
</span><del>-do_action( "install_themes_pre_{$tab}" );
</del><ins>+if ( $tab ) {
+       do_action( "install_themes_pre_{$tab}" );
+}
</ins><span class="cx"> 
</span><span class="cx"> $help_overview =
</span><span class="cx">  '<p>' . sprintf(__('You can find additional themes for your site by using the Theme Browser/Installer on this screen, which will display themes from the <a href="%s" target="_blank">WordPress.org Theme Directory</a>. These themes are designed and developed by third parties, are available free of charge, and are compatible with the license WordPress uses.'), 'https://wordpress.org/themes/') . '</p>' .
</span><span class="lines">@@ -73,14 +99,39 @@
</span><span class="cx"> );
</span><span class="cx"> 
</span><span class="cx"> include(ABSPATH . 'wp-admin/admin-header.php');
</span><ins>+
</ins><span class="cx"> ?>
</span><span class="cx"> <div class="wrap">
</span><del>-<h2><?php echo esc_html( $title ); ?></h2>
-<?php
</del><ins>+        <h2>
+               <?php echo esc_html( $title ); ?>
+               <a class="upload button button-secondary"><?php esc_html_e( 'Upload Theme' ); ?></a>
+       </h2>
</ins><span class="cx"> 
</span><del>-$wp_list_table->views(); ?>
</del><ins>+        <div class="upload-theme">
+       <?php install_themes_upload(); ?>
+       </div>
</ins><span class="cx"> 
</span><del>-<br class="clear" />
</del><ins>+        <div class="theme-navigation">
+               <span class="theme-count"></span>
+               <span class="theme-section current" data-sort="featured"><?php esc_html_e( 'Featured' ); ?></span>
+               <span class="theme-section" data-sort="popular"><?php esc_html_e( 'Popular' ); ?></span>
+               <span class="theme-section" data-sort="new"><?php esc_html_e( 'Latest' ); ?></span>
+               <div class="theme-top-filters">
+                       <span class="theme-filter" data-filter="photoblogging">Photography</span>
+                       <span class="theme-filter" data-filter="responsive-layout">Responsive</span>
+                       <span class="theme-filter more-filters">More</span>
+               </div>
+               <div class="more-filters-container">
+                       Display more filters.
+               </div>
+       </div>
+       <div class="theme-browser"></div>
+       <div class="theme-overlay"></div>
+       <div id="theme-installer" class="wp-full-overlay expanded"></div>
+
+       <span class="spinner"></span>
+
+       <br class="clear" />
</ins><span class="cx"> <?php
</span><span class="cx"> /**
</span><span class="cx">  * Fires at the top of each of the tabs on the Install Themes page.
</span><span class="lines">@@ -93,8 +144,68 @@
</span><span class="cx">  *
</span><span class="cx">  * @param int $paged Number of the current page of results being viewed.
</span><span class="cx">  */
</span><del>-do_action( "install_themes_{$tab}", $paged );
</del><ins>+if ( $tab ) {
+       do_action( "install_themes_{$tab}", $paged );
+}
</ins><span class="cx"> ?>
</span><span class="cx"> </div>
</span><ins>+
+<script id="tmpl-theme" type="text/template">
+       <# if ( data.screenshot_url ) { #>
+               <div class="theme-screenshot">
+                       <img src="{{ data.screenshot_url }}" alt="" />
+               </div>
+       <# } else { #>
+               <div class="theme-screenshot blank"></div>
+       <# } #>
+       <span class="more-details"><?php _ex( 'Details &amp; Preview', 'theme' ); ?></span>
+       <div class="theme-author"><?php printf( __( 'By %s' ), '{{ data.author }}' ); ?></div>
+       <h3 class="theme-name">{{ data.name }}</h3>
+
+       <div class="theme-actions">
+               <a class="button button-primary" href="{{ data.installURI }}"><?php esc_html_e( 'Install' ); ?></a>
+               <a class="button button-secondary preview install-theme-preview" href="#"><?php esc_html_e( 'Preview' ); ?></a>
+       </div>
+</script>
+
+<script id="tmpl-theme-preview" type="text/template">
+       <div class="wp-full-overlay-sidebar">
+               <div class="wp-full-overlay-header">
+                       <a href="" class="close-full-overlay button-secondary"><?php _e( 'Close' ); ?></a>
+                       <a href="{{ data.installURI }}" class="button button-primary theme-install"><?php _e( 'Install' ); ?></a>
+               </div>
+               <div class="wp-full-overlay-sidebar-content">
+                       <div class="install-theme-info">
+                               <h3 class="theme-name">{{ data.name }}</h3>
+                               <span class="theme-by"><?php printf( __( 'By %s' ), '{{ data.author }}' ); ?></span>
+
+                               <img class="theme-screenshot" src="{{ data.screenshot_url }}" alt="" />
+
+                               <div class="theme-details">
+                                       <div class="rating rating-{{ Math.round( data.rating / 10 ) * 10 }}">
+                                               <span class="one"></span>
+                                               <span class="two"></span>
+                                               <span class="three"></span>
+                                               <span class="four"></span>
+                                               <span class="five"></span>
+                                               <p class="votes"><?php printf( __( 'Based on %s ratings.' ), '{{ data.num_ratings }}' ); ?></p>
+                                       </div>
+                                       <div class="theme-version"><?php printf( __( 'Version: %s' ), '{{ data.version }}' ); ?></div>
+                                       <div class="theme-description">{{ data.description }}</div>
+                               </div>
+                       </div>
+               </div>
+               <div class="wp-full-overlay-footer">
+                       <a href="" class="collapse-sidebar" title="<?php esc_attr_e( 'Collapse Sidebar' ); ?>">
+                               <span class="collapse-sidebar-label"><?php _e( 'Collapse' ); ?></span>
+                               <span class="collapse-sidebar-arrow"></span>
+                       </a>
+               </div>
+       </div>
+       <div class="wp-full-overlay-main">
+               <iframe src="{{ data.preview_url }}" />
+       </div>
+</script>
+
</ins><span class="cx"> <?php
</span><span class="cx"> include(ABSPATH . 'wp-admin/admin-footer.php');
</span></span></pre></div>
<a id="trunksrcwpadminupdatephp"></a>
<div class="modfile"><h4>Modified: trunk/src/wp-admin/update.php (27498 => 27499)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-admin/update.php    2014-03-11 04:19:25 UTC (rev 27498)
+++ trunk/src/wp-admin/update.php       2014-03-11 07:46:27 UTC (rev 27499)
</span><span class="lines">@@ -202,7 +202,7 @@
</span><span class="cx"> 
</span><span class="cx">          include_once ABSPATH . 'wp-admin/includes/theme-install.php'; //for themes_api..
</span><span class="cx"> 
</span><del>-               check_admin_referer('install-theme_' . $theme);
</del><ins>+                check_admin_referer( 'install-theme' );
</ins><span class="cx">           $api = themes_api('theme_information', array('slug' => $theme, 'fields' => array('sections' => false, 'tags' => false) ) ); //Save on a bit of bandwidth.
</span><span class="cx"> 
</span><span class="cx">          if ( is_wp_error($api) )
</span></span></pre></div>
<a id="trunksrcwpincludesscriptloaderphp"></a>
<div class="modfile"><h4>Modified: trunk/src/wp-includes/script-loader.php (27498 => 27499)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-includes/script-loader.php  2014-03-11 04:19:25 UTC (rev 27498)
+++ trunk/src/wp-includes/script-loader.php     2014-03-11 07:46:27 UTC (rev 27499)
</span><span class="lines">@@ -454,11 +454,7 @@
</span><span class="cx">          $scripts->add( 'admin-widgets', "/wp-admin/js/widgets$suffix.js", array( 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-droppable' ), false, 1 );
</span><span class="cx"> 
</span><span class="cx">          $scripts->add( 'theme', "/wp-admin/js/theme$suffix.js", array( 'wp-backbone' ), false, 1 );
</span><del>-               $scripts->add( 'theme-install', "/wp-admin/js/theme-install$suffix.js", array( 'jquery' ), false, 1 );
</del><span class="cx"> 
</span><del>-               // @todo: Core no longer uses theme-preview.js. Remove?
-               $scripts->add( 'theme-preview', "/wp-admin/js/theme-preview$suffix.js", array( 'thickbox', 'jquery' ), false, 1 );
-
</del><span class="cx">           $scripts->add( 'inline-edit-post', "/wp-admin/js/inline-edit-post$suffix.js", array( 'jquery', 'suggest', 'heartbeat' ), false, 1 );
</span><span class="cx">          did_action( 'init' ) && $scripts->localize( 'inline-edit-post', 'inlineEditL10n', array(
</span><span class="cx">                  'error' => __('Error while saving the changes.'),
</span></span></pre>
</div>
</div>

</body>
</html>