<!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>[23006] trunk: Final round of media UX improvements.</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, #logmsg > ol { margin-left: 0; 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/23006">23006</a></dd>
<dt>Author</dt> <dd>ryan</dd>
<dt>Date</dt> <dd>2012-12-04 01:26:03 +0000 (Tue, 04 Dec 2012)</dd>
</dl>

<h3>Log Message</h3>
<pre>Final round of media UX improvements.

Props koopersmith
fixes <a href="http://core.trac.wordpress.org/ticket/21390">#21390</a> <a href="http://core.trac.wordpress.org/ticket/22502">#22502</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpadminjscustombackgroundjs">trunk/wp-admin/js/custom-background.js</a></li>
<li><a href="#trunkwpadminjscustomheaderjs">trunk/wp-admin/js/custom-header.js</a></li>
<li><a href="#trunkwpincludescssmediaviewsrtlcss">trunk/wp-includes/css/media-views-rtl.css</a></li>
<li><a href="#trunkwpincludescssmediaviewscss">trunk/wp-includes/css/media-views.css</a></li>
<li><a href="#trunkwpincludesjsmediaeditorjs">trunk/wp-includes/js/media-editor.js</a></li>
<li><a href="#trunkwpincludesjsmediaviewsjs">trunk/wp-includes/js/media-views.js</a></li>
<li><a href="#trunkwpincludesmediaphp">trunk/wp-includes/media.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpadminjscustombackgroundjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/js/custom-background.js (23005 => 23006)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/js/custom-background.js        2012-12-04 00:51:02 UTC (rev 23005)
+++ trunk/wp-admin/js/custom-background.js        2012-12-04 01:26:03 UTC (rev 23006)
</span><span class="lines">@@ -37,8 +37,8 @@
</span><span class="cx">                                 }
</span><span class="cx">                         });
</span><span class="cx"> 
</span><del>-                        frame.toolbar.on( 'activate:select', function() {
-                                frame.toolbar.view().set({
</del><ins>+                        frame.on( 'toolbar:render:select', function( view ) {
+                                view.set({
</ins><span class="cx">                                         select: {
</span><span class="cx">                                                 style: 'primary',
</span><span class="cx">                                                 text:  $el.data('update'),
</span></span></pre></div>
<a id="trunkwpadminjscustomheaderjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/js/custom-header.js (23005 => 23006)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/js/custom-header.js        2012-12-04 00:51:02 UTC (rev 23005)
+++ trunk/wp-admin/js/custom-header.js        2012-12-04 01:26:03 UTC (rev 23006)
</span><span class="lines">@@ -24,8 +24,8 @@
</span><span class="cx">                                 }
</span><span class="cx">                         });
</span><span class="cx"> 
</span><del>-                        frame.toolbar.on( 'activate:select', function() {
-                                frame.toolbar.view().set({
</del><ins>+                        frame.on( 'toolbar:render:select', function( view ) {
+                                view.set({
</ins><span class="cx">                                         select: {
</span><span class="cx">                                                 style: 'primary',
</span><span class="cx">                                                 text:  $el.data('update'),
</span></span></pre></div>
<a id="trunkwpincludescssmediaviewsrtlcss"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/css/media-views-rtl.css (23005 => 23006)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/css/media-views-rtl.css        2012-12-04 00:51:02 UTC (rev 23005)
+++ trunk/wp-includes/css/media-views-rtl.css        2012-12-04 01:26:03 UTC (rev 23006)
</span><span class="lines">@@ -1,25 +1,14 @@
</span><span class="cx"> /**
</span><span class="cx">  * Modal
</span><span class="cx">  */
</span><del>-.media-modal-title {
-        left: auto;
-        right: 0;
-}
-
</del><span class="cx"> .media-modal-close {
</span><span class="cx">         right: auto;
</span><del>-        left: 0;
</del><ins>+        left: 7px;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * Toolbar
</span><span class="cx">  */
</span><del>-.media-frame-toolbar &gt; .media-toolbar {
-        left: 0;
-        right: 200px;
-}
-
-
</del><span class="cx"> .media-toolbar-primary {
</span><span class="cx">         float: left;
</span><span class="cx"> }
</span><span class="lines">@@ -93,21 +82,51 @@
</span><span class="cx">  * Menu
</span><span class="cx">  */
</span><span class="cx"> .media-menu {
</span><del>-        left: auto;
-        right: 0;
</del><span class="cx">         border-right: 0;
</span><span class="cx">         border-left: 1px solid #d9d9d9;
</span><span class="cx">         box-shadow: inset 6px 0 6px -6px rgba( 0, 0, 0, 0.2 )
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Router
+ */
+.media-router &gt; a {
+        float: right;
+        border-right: 0;
+        border-left: 1px solid #dfdfdf;
+}
+.media-router &gt; a:last-child {
+        border-left: 0;
+}
+
+/**
</ins><span class="cx">  * Frame
</span><span class="cx">  */
</span><del>-.media-frame .region-content {
</del><ins>+.media-frame-menu {
+        left: auto;
+        right: 0;
+}
+
+.media-frame-title,
+.media-frame-router,
+.media-frame-content,
+.media-frame-toolbar {
</ins><span class="cx">         left: 0;
</span><span class="cx">         right: 200px;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.media-frame.hide-menu .media-frame-title,
+.media-frame.hide-menu .media-frame-router,
+.media-frame.hide-menu .media-frame-toolbar,
+.media-frame.hide-menu .media-frame-content {
+        right: 0;
+}
+
+.media-frame.hide-menu .media-frame-menu {
+        left: auto;
+        right: -200px;
+}
+
</ins><span class="cx"> /**
</span><span class="cx">  * Attachment Browser Filters
</span><span class="cx">  */
</span><span class="lines">@@ -226,30 +245,6 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * Selection Preview
- */
-.selected-img {
-        float: right;
-        margin-right: 0;
-        margin-left: 14px;
-}
-
-.selection-preview img {
-        float: right;
-        margin-left: 0;
-        margin-right: 1px;
-}
-
-.selection-preview .count {
-        right: auto;
-        left: 0;
-}
-
-.selection-preview .clear-selection {
-        float: right;
-}
-
-/**
</del><span class="cx">  * Attachment Details
</span><span class="cx">  */
</span><span class="cx"> .attachment-info .thumbnail {
</span><span class="lines">@@ -289,8 +284,10 @@
</span><span class="cx">  * Responsive layout
</span><span class="cx">  */
</span><span class="cx"> @media only screen and (max-width: 900px) {
</span><del>-        .media-frame .region-content,
-        .media-frame-toolbar &gt; .media-toolbar {
</del><ins>+        .media-frame-title,
+        .media-frame-router,
+        .media-frame-content,
+        .media-frame-toolbar {
</ins><span class="cx">                 left: 0;
</span><span class="cx">                 right: 140px;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkwpincludescssmediaviewscss"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/css/media-views.css (23005 => 23006)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/css/media-views.css        2012-12-04 00:51:02 UTC (rev 23005)
+++ trunk/wp-includes/css/media-views.css        2012-12-04 01:26:03 UTC (rev 23006)
</span><span class="lines">@@ -80,10 +80,10 @@
</span><span class="cx">  */
</span><span class="cx"> .media-modal {
</span><span class="cx">         position: fixed;
</span><del>-        top: 60px;
-        left: 40px;
-        right: 40px;
-        bottom: 40px;
</del><ins>+        top: 30px;
+        left: 30px;
+        right: 30px;
+        bottom: 30px;
</ins><span class="cx">         z-index: 160000;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -94,42 +94,24 @@
</span><span class="cx">         right: 0;
</span><span class="cx">         bottom: 0;
</span><span class="cx">         background: #000;
</span><del>-        opacity: 0.8;
</del><ins>+        opacity: 0.7;
</ins><span class="cx">         z-index: 159900;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.media-modal-backdrop div,
-.uploader-window-content {
</del><ins>+.media-modal-close {
</ins><span class="cx">         position: absolute;
</span><del>-        top: 10px;
-        left: 10px;
-        right: 10px;
-        bottom: 10px;
-        border: 1px dashed rgba( 255, 255, 255, 0.5 );
</del><ins>+        top: 7px;
+        right: 7px;
+        width: 30px;
+        height: 30px;
+        z-index: 1000;
</ins><span class="cx"> }
</span><del>-
-.media-modal-title {
-        position: absolute;
-        top: -40px;
-        left: 0;
-        height: 40px;
-        padding: 0;
-        margin: 0;
-
-        line-height: 40px;
-        color: #fff;
-        font-size: 16px;
-        font-weight: 200;
-        text-shadow: 0 0 16px rgba( 0, 0, 0, 0.6 );
-}
-
-.media-modal-close {
-        position: absolute;
-        top: -27px;
-        right: 0;
</del><ins>+.media-modal-close span {
+        display: block;
+        margin: 8px auto 0;
+        width: 15px;
</ins><span class="cx">         height: 15px;
</span><del>-        width: 15px;
-        background-position: -80px 0;
</del><ins>+        background-position: -100px 0;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> .media-modal-close:active {
</span><span class="lines">@@ -165,18 +147,6 @@
</span><span class="cx">         border: 0 solid #dfdfdf;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.media-frame-toolbar &gt; .media-toolbar {
-        top: auto;
-        left: 200px;
-        bottom: 0;
-        border-width: 1px 0 0 0;
-        box-shadow: 0 -4px 4px -4px rgba( 0, 0, 0, 0.1 );
-}
-
-.hide-toolbar .media-frame-toolbar &gt; .media-toolbar {
-        bottom: -61px;
-}
-
</del><span class="cx"> .media-toolbar-primary {
</span><span class="cx">         float: right;
</span><span class="cx"> }
</span><span class="lines">@@ -238,11 +208,6 @@
</span><span class="cx">         width: 100%;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.media-sidebar .selection-preview {
-        display: block;
-        padding-top: 5px;
-}
-
</del><span class="cx"> .media-sidebar h3 {
</span><span class="cx">         position: relative;
</span><span class="cx">         font-weight: bold;
</span><span class="lines">@@ -361,11 +326,10 @@
</span><span class="cx">         position: absolute;
</span><span class="cx">         top: 0;
</span><span class="cx">         left: 0;
</span><ins>+        right: 0;
</ins><span class="cx">         bottom: 0;
</span><del>-        width: 199px;
</del><span class="cx">         margin: 0;
</span><span class="cx">         padding: 16px 0;
</span><del>-        z-index: 200;
</del><span class="cx">         border-right: 1px solid #d9d9d9;
</span><span class="cx">         box-shadow: inset -6px 0 6px -6px rgba( 0, 0, 0, 0.2 );
</span><span class="cx">         -webkit-user-select: none;
</span><span class="lines">@@ -374,7 +338,8 @@
</span><span class="cx">         user-select: none;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.media-menu li {
</del><ins>+.media-menu &gt; a {
+        display: block;
</ins><span class="cx">         position: relative;
</span><span class="cx">         padding: 4px 20px;
</span><span class="cx">         margin: 0;
</span><span class="lines">@@ -382,14 +347,16 @@
</span><span class="cx">         font-size: 14px;
</span><span class="cx">         color: #21759B;
</span><span class="cx">         text-shadow: 0 1px 0 #fff;
</span><ins>+        text-decoration: none;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-.media-menu-item {
-        cursor: pointer;
</del><ins>+.media-menu &gt; a:hover {
+        color: #21759B;
+        background: rgba( 0, 0, 0, 0.04 );
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-.media-menu li:hover {
-        background: rgba( 0, 0, 0, 0.04 );
</del><ins>+.media-menu &gt; a:active {
+        outline: none;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> .media-menu .active,
</span><span class="lines">@@ -407,6 +374,64 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Menu
+ */
+.media-router {
+        position: relative;
+        padding: 0 6px;
+        margin: 0;
+        clear: both;
+        -webkit-user-select: none;
+        -moz-user-select: none;
+        -ms-user-select: none;
+        user-select: none;
+}
+
+.media-router &gt; a {
+        position: relative;
+        float: left;
+        padding: 2px 10px;
+        margin: 0;
+        height: 18px;
+        line-height: 18px;
+        font-size: 14px;
+        border-right: 1px solid #dfdfdf;
+        text-shadow: 0 1px 0 #fff;
+        text-decoration: none;
+}
+
+.media-router &gt; a:last-child {
+        border-right: 0;
+}
+
+.media-router &gt; a:active,
+.media-router &gt; a:focus {
+        outline: none;
+}
+
+.media-router .active,
+.media-router .active:hover {
+        color: #333;
+}
+
+.media-router .active:after {
+        content: '';
+        display: block;
+        margin: -100px auto 0;
+        width: 7px;
+        height: 7px;
+        background: #fff;
+        box-shadow: 1px 1px 1px rgba( 0, 0, 0, 0.2 );
+        z-index: 300;
+
+        -webkit-transform: rotate( 45deg ) translate( 75px, 75px );
+        -moz-transform:    rotate( 45deg ) translate( 75px, 75px );
+        -ms-transform:     rotate( 45deg ) translate( 75px, 75px );
+        -o-transform:      rotate( 45deg ) translate( 75px, 75px );
+        transform:         rotate( 45deg ) translate( 75px, 75px );
+}
+
+/**
</ins><span class="cx">  * Frame
</span><span class="cx">  */
</span><span class="cx"> .media-frame {
</span><span class="lines">@@ -418,11 +443,40 @@
</span><span class="cx">         bottom: 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.media-frame .region-content {
</del><ins>+.media-frame-menu {
</ins><span class="cx">         position: absolute;
</span><span class="cx">         top: 0;
</span><ins>+        left: 0;
+        bottom: 0;
+        width: 199px;
+        z-index: 150;
+}
+
+.media-frame-title {
+        position: absolute;
+        top: 0;
</ins><span class="cx">         left: 200px;
</span><span class="cx">         right: 0;
</span><ins>+        height: 45px;
+        z-index: 200;
+}
+
+.media-frame-router {
+        position: absolute;
+        top: 45px;
+        left: 200px;
+        right: 0;
+        height: 30px;
+        z-index: 200;
+        border-bottom: 1px solid #dfdfdf;
+        box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.1 );
+}
+
+.media-frame-content {
+        position: absolute;
+        top: 75px;
+        left: 200px;
+        right: 0;
</ins><span class="cx">         bottom: 61px;
</span><span class="cx">         height: auto;
</span><span class="cx">         width: auto;
</span><span class="lines">@@ -430,14 +484,62 @@
</span><span class="cx">         overflow: auto;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.media-frame.hide-toolbar .region-content {
</del><ins>+.media-frame-toolbar {
+        position: absolute;
+        left: 200px;
+        right: 0;
</ins><span class="cx">         bottom: 0;
</span><ins>+        height: 60px;
+        z-index: 100;
+        border: 0 solid #dfdfdf;
+        border-width: 1px 0 0 0;
+        box-shadow: 0 -4px 4px -4px rgba( 0, 0, 0, 0.1 );
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.media-frame.hide-menu .media-frame-title,
+.media-frame.hide-menu .media-frame-router,
+.media-frame.hide-menu .media-frame-toolbar,
+.media-frame.hide-menu .media-frame-content {
+        left: 0;
+}
+
+.media-frame.hide-menu .media-frame-menu {
+        left: -200px;
+}
+
+.media-frame.hide-toolbar .media-frame-content {
+        bottom: 0;
+}
+
+.media-frame.hide-toolbar .media-frame-toolbar {
+        bottom: -61px;
+}
+
+.media-frame.hide-router .media-frame-content {
+        top: 45px;
+}
+
+.media-frame.hide-router .media-frame-router {
+        display: none;
+}
+
+.media-frame.hide-router .media-frame-title {
+        border-bottom: 1px solid #dfdfdf;
+        box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.1 );
+}
+
</ins><span class="cx"> .media-frame .media-toolbar .add-to-gallery {
</span><span class="cx">         display: none;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.media-frame-title h1 {
+        padding: 0 16px;
+        font-size: 22px;
+        font-weight: 200;
+        line-height: 45px;
+        margin: 0;
+}
+
</ins><span class="cx"> /**
</span><span class="cx">  * Iframes
</span><span class="cx">  */
</span><span class="lines">@@ -721,6 +823,9 @@
</span><span class="cx">  * Attachments Browser
</span><span class="cx">  */
</span><span class="cx"> .media-frame .attachments-browser {
</span><ins>+        position: relative;
+        width: 100%;
+        height: 100%;
</ins><span class="cx">         overflow: hidden;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -903,7 +1008,12 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> .uploader-window-content {
</span><del>-        border-color: #fff;
</del><ins>+        position: absolute;
+        top: 10px;
+        left: 10px;
+        right: 10px;
+        bottom: 10px;
+        border: 1px dashed #fff;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> .uploader-window h3 {
</span><span class="lines">@@ -956,6 +1066,10 @@
</span><span class="cx">         margin: 4em 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.uploader-inline .has-upload-message .upload-ui {
+        margin: 0 0 4em;
+}
+
</ins><span class="cx"> .uploader-inline h3 {
</span><span class="cx">         font-size: 20px;
</span><span class="cx">         line-height: 28px;
</span><span class="lines">@@ -963,6 +1077,12 @@
</span><span class="cx">         margin-bottom: 1.6em;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.uploader-inline .has-upload-message .upload-instructions {
+        font-size: 14px;
+        color: #464646;
+        font-weight: normal;
+}
+
</ins><span class="cx"> .uploader-inline .drop-instructions {
</span><span class="cx">         display: none;
</span><span class="cx"> }
</span><span class="lines">@@ -1058,7 +1178,7 @@
</span><span class="cx">         vertical-align: top;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.media-selection .attachment img {
</del><ins>+.media-selection .attachment .icon {
</ins><span class="cx">         width: 50%;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1098,69 +1218,6 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * Selection Preview
- */
-.selection-preview {
-        position: relative;
-        height: 60px;
-        overflow: hidden;
-}
-
-.selected-img {
-        float: left;
-        position: relative;
-        margin-right: 14px;
-}
-
-.selection-preview img {
-        max-width: 40px;
-        max-height: 40px;
-        float: left;
-        margin-top: 6px;
-        margin-left: 1px;
-        border: 2px solid white;
-        box-shadow:
-            0 0 0 1px #ccc,
-            3px 3px 0 0 #fff,
-            3px 3px 0 1px #ccc,
-            6px 6px 0 0 #fff,
-            6px 6px 0 1px #ccc;
-}
-
-.selection-preview .selected-count-1 img {
-        margin-top: 8px;
-        box-shadow: 0 0 0 1px #ccc;
-}
-
-.selection-preview .selected-count-2 img {
-        margin-top: 7px;
-        box-shadow:
-            0 0 0 1px #ccc,
-            3px 3px 0 0 #fff,
-            3px 3px 0 1px #ccc;
-}
-
-.selection-preview .count {
-        position: absolute;
-        bottom: 0;
-        right: 0;
-        height: 16px;
-        min-width: 8px;
-        padding: 0 4px;
-        font-size: 12px;
-        text-align: center;
-        font-weight: bold;
-        color: #999;
-        background: #fff;
-        box-shadow: -1px -1px 2px -1px rgba( 0, 0, 0, 0.2 );
-}
-
-.selection-preview .clear-selection {
-        float: left;
-        line-height: 60px;
-}
-
-/**
</del><span class="cx">  * Spinner
</span><span class="cx">  */
</span><span class="cx"> .media-sidebar .settings-save-status {
</span><span class="lines">@@ -1297,21 +1354,17 @@
</span><span class="cx"> .embed-url {
</span><span class="cx">         display: block;
</span><span class="cx">         position: relative;
</span><del>-        height: 75px;
-        padding: 16px 16px;
</del><ins>+        height: 40px;
+        padding: 0 16px 16px;
</ins><span class="cx">         margin: 0;
</span><del>-        z-index: 50;
</del><ins>+        z-index: 250;
+        background: #fff;
</ins><span class="cx">         border-bottom: 1px solid #dfdfdf;
</span><span class="cx">         box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.1 );
</span><span class="cx">         font-size: 18px;
</span><span class="cx">         font-weight: 200;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.embed-url span {
-        display: block;
-        padding: 4px 0 6px 2px;
-}
-
</del><span class="cx"> .media-frame .embed-url input {
</span><span class="cx">         font-size: 18px;
</span><span class="cx">         padding: 12px 14px;
</span><span class="lines">@@ -1324,7 +1377,7 @@
</span><span class="cx"> .embed-image-settings {
</span><span class="cx">         position: absolute;
</span><span class="cx">         background: #f5f5f5;
</span><del>-        top: 108px;
</del><ins>+        top: 57px;
</ins><span class="cx">         left: 0;
</span><span class="cx">         right: 0;
</span><span class="cx">         bottom: 0;
</span><span class="lines">@@ -1388,41 +1441,18 @@
</span><span class="cx">  * Responsive layout
</span><span class="cx">  */
</span><span class="cx"> @media only screen and (max-width: 900px) {
</span><del>-        .media-modal {
-                bottom: 20px;
-                left: 20px;
-                right: 20px;
-                top: 40px;
-        }
-
-        .media-modal-title {
-                height: 30px;
-                line-height: 30px;
-                top: -30px;
-        }
-
-        .media-modal-close {
-                top: -23px;
-        }
-
-        .media-modal-backdrop div,
-        .uploader-window-content {
-                top: 5px;
-                left: 5px;
-                right: 5px;
-                bottom: 5px;
-        }
-
-        .media-menu {
</del><ins>+        .media-frame-menu {
</ins><span class="cx">                 width: 139px;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        .media-menu li {
</del><ins>+        .media-menu &gt; a {
</ins><span class="cx">                 padding: 4px 10px;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        .media-frame .region-content,
-        .media-frame-toolbar &gt; .media-toolbar {
</del><ins>+        .media-frame-title,
+        .media-frame-router,
+        .media-frame-content,
+        .media-frame-toolbar {
</ins><span class="cx">                 left: 140px;
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkwpincludesjsmediaeditorjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/js/media-editor.js (23005 => 23006)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/js/media-editor.js        2012-12-04 00:51:02 UTC (rev 23005)
+++ trunk/wp-includes/js/media-editor.js        2012-12-04 01:26:03 UTC (rev 23006)
</span><span class="lines">@@ -384,7 +384,7 @@
</span><span class="cx"> 
</span><span class="cx">                         workflow = workflows[ id ] = wp.media( _.defaults( options || {}, {
</span><span class="cx">                                 frame:    'post',
</span><del>-                                state:    'upload',
</del><ins>+                                state:    'insert',
</ins><span class="cx">                                 title:    wp.media.view.l10n.addMedia,
</span><span class="cx">                                 multiple: true
</span><span class="cx">                         } ) );
</span><span class="lines">@@ -408,11 +408,13 @@
</span><span class="cx">                         }, this );
</span><span class="cx"> 
</span><span class="cx">                         workflow.state('embed').on( 'select', function() {
</span><del>-                                var embed = workflow.state().toJSON();
</del><ins>+                                var state = workflow.state(),
+                                        type = state.get('type'),
+                                        embed = state.props.toJSON();
</ins><span class="cx"> 
</span><span class="cx">                                 embed.url = embed.url || '';
</span><span class="cx"> 
</span><del>-                                if ( 'link' === embed.type ) {
</del><ins>+                                if ( 'link' === type ) {
</ins><span class="cx">                                         _.defaults( embed, {
</span><span class="cx">                                                 title:   embed.url,
</span><span class="cx">                                                 linkUrl: embed.url
</span><span class="lines">@@ -420,7 +422,7 @@
</span><span class="cx"> 
</span><span class="cx">                                         this.send.link( embed );
</span><span class="cx"> 
</span><del>-                                } else if ( 'image' === embed.type ) {
</del><ins>+                                } else if ( 'image' === type ) {
</ins><span class="cx">                                         _.defaults( embed, {
</span><span class="cx">                                                 title:   embed.url,
</span><span class="cx">                                                 linkUrl: '',
</span></span></pre></div>
<a id="trunkwpincludesjsmediaviewsjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/js/media-views.js (23005 => 23006)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/js/media-views.js        2012-12-04 00:51:02 UTC (rev 23005)
+++ trunk/wp-includes/js/media-views.js        2012-12-04 01:26:03 UTC (rev 23006)
</span><span class="lines">@@ -68,65 +68,71 @@
</span><span class="cx">          * wp.media.controller.Region
</span><span class="cx">          */
</span><span class="cx">         media.controller.Region = function( options ) {
</span><del>-                _.extend( this, _.pick( options || {}, 'id', 'controller', 'selector' ) );
-
-                this.on( 'activate:empty', this.empty, this );
-                this.mode('empty');
</del><ins>+                _.extend( this, _.pick( options || {}, 'id', 'view', 'selector' ) );
</ins><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         // Use Backbone's self-propagating `extend` inheritance method.
</span><span class="cx">         media.controller.Region.extend = Backbone.Model.extend;
</span><span class="cx"> 
</span><del>-        _.extend( media.controller.Region.prototype, Backbone.Events, {
-                trigger: (function() {
-                        var eventSplitter = /\s+/,
-                                trigger = Backbone.Events.trigger;
</del><ins>+        _.extend( media.controller.Region.prototype, {
+                mode: function( mode ) {
+                        if ( ! mode )
+                                return this._mode;
</ins><span class="cx"> 
</span><del>-                        return function( events ) {
-                                var mode = ':' + this._mode,
-                                        modeEvents = events.split( eventSplitter ).join( mode ) + mode;
-
-                                trigger.apply( this, arguments );
-                                trigger.apply( this, [ modeEvents ].concat( _.rest( arguments ) ) );
</del><ins>+                        // Bail if we're trying to change to the current mode.
+                        if ( mode === this._mode )
</ins><span class="cx">                                 return this;
</span><del>-                        };
-                }()),
</del><span class="cx"> 
</span><del>-                mode: function( mode ) {
-                        if ( mode ) {
-                                this.trigger( 'deactivate', this );
-                                this._mode = mode;
-                                return this.trigger( 'activate', this );
-                        }
-                        return this._mode;
</del><ins>+                        this.trigger('deactivate');
+                        this._mode = mode;
+                        this.render( mode );
+                        this.trigger('activate');
+                        return this;
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                view: function( view ) {
-                        var previous = this._view,
-                                mode = this._mode,
-                                id = this.id;
</del><ins>+                render: function( mode ) {
+                        // If no mode is provided, just re-render the current mode.
+                        // If the provided mode isn't active, perform a full switch.
+                        if ( mode &amp;&amp; mode !== this._mode )
+                                return this.mode( mode );
</ins><span class="cx"> 
</span><del>-                        // If no argument is provided, return the current view.
-                        if ( ! view )
-                                return previous;
</del><ins>+                        var set = { view: null },
+                                view;
</ins><span class="cx"> 
</span><del>-                        // If we're attempting to switch to the current view, bail.
-                        if ( view === previous )
</del><ins>+                        this.trigger( 'create', set );
+                        view = set.view;
+                        this.trigger( 'render', view );
+                        if ( view )
+                                this.set( view );
+                        return this;
+                },
+
+                get: function() {
+                        return this.view.views.first( this.selector );
+                },
+
+                set: function( views, options ) {
+                        if ( options )
+                                options.add = false;
+                        return this.view.views.set( this.selector, views, options );
+                },
+
+                trigger: function( event ) {
+                        var base;
+                        if ( ! this._mode )
</ins><span class="cx">                                 return;
</span><span class="cx"> 
</span><del>-                        // Add classes to the new view.
-                        if ( id )
-                                view.$el.addClass( 'region-' + id );
</del><ins>+                        var args = _.toArray( arguments );
+                        base = this.id + ':' + event;
</ins><span class="cx"> 
</span><del>-                        if ( mode )
-                                view.$el.addClass( 'mode-' + mode );
</del><ins>+                        // Trigger `region:action:mode` event.
+                        args[0] = base + ':' + this._mode;
+                        this.view.trigger.apply( this.view, args );
</ins><span class="cx"> 
</span><del>-                        this.controller.views.set( this.selector, view );
-                        this._view = view;
-                },
-
-                empty: function() {
-                        this.view( new media.View() );
</del><ins>+                        // Trigger `region:action` event.
+                        args[0] = base;
+                        this.view.trigger.apply( this.view, args );
+                        return this;
</ins><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><span class="lines">@@ -208,31 +214,86 @@
</span><span class="cx">         // wp.media.controller.State
</span><span class="cx">         // ---------------------------
</span><span class="cx">         media.controller.State = Backbone.Model.extend({
</span><del>-                initialize: function() {
-                        this.on( 'activate', this._activate, this );
</del><ins>+                constructor: function() {
+                        this.on( 'activate', this._preActivate, this );
</ins><span class="cx">                         this.on( 'activate', this.activate, this );
</span><ins>+                        this.on( 'activate', this._postActivate, this );
</ins><span class="cx">                         this.on( 'deactivate', this._deactivate, this );
</span><span class="cx">                         this.on( 'deactivate', this.deactivate, this );
</span><span class="cx">                         this.on( 'reset', this.reset, this );
</span><ins>+                        this.on( 'ready', this._ready, this );
+                        this.on( 'ready', this.ready, this );
+
+                        this.on( 'change:menu', this._updateMenu, this );
+
+                        Backbone.Model.apply( this, arguments );
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><ins>+                ready: function() {},
</ins><span class="cx">                 activate: function() {},
</span><del>-                _activate: function() {
</del><ins>+                deactivate: function() {},
+                reset: function() {},
+
+                _ready: function() {
+                        this._updateMenu();
+                },
+
+                _preActivate: function() {
</ins><span class="cx">                         this.active = true;
</span><ins>+                },
</ins><span class="cx"> 
</span><del>-                        this.menu();
-                        this.toolbar();
-                        this.content();
</del><ins>+                _postActivate: function() {
+                        this.on( 'change:menu', this._menu, this );
+                        this.on( 'change:titleMode', this._title, this );
+                        this.on( 'change:content', this._content, this );
+                        this.on( 'change:toolbar', this._toolbar, this );
+
+                        this.frame.on( 'title:render:default', this._renderTitle, this );
+
+                        this._title();
+                        this._menu();
+                        this._toolbar();
+                        this._content();
+                        this._router();
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                deactivate: function() {},
</del><ins>+
</ins><span class="cx">                 _deactivate: function() {
</span><span class="cx">                         this.active = false;
</span><ins>+
+                        this.frame.off( 'title:render:default', this._renderTitle, this );
+
+                        this.off( 'change:menu', this._menu, this );
+                        this.off( 'change:titleMode', this._title, this );
+                        this.off( 'change:content', this._content, this );
+                        this.off( 'change:toolbar', this._toolbar, this );
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                reset: function() {},
</del><ins>+                _title: function() {
+                        this.frame.title.render( this.get('titleMode') || 'default' );
+                },
</ins><span class="cx"> 
</span><del>-                menu: function() {
</del><ins>+                _renderTitle: function( view ) {
+                        view.$el.text( this.get('title') || '' );
+                },
+
+                _router: function() {
+                        var router = this.frame.router,
+                                mode = this.get('router'),
+                                view;
+
+                        this.frame.$el.toggleClass( 'hide-router', ! mode );
+                        if ( ! mode )
+                                return;
+
+                        this.frame.router.render( mode );
+
+                        view = router.get();
+                        if ( view.select )
+                                view.select( this.frame.content.mode() );
+                },
+
+                _menu: function() {
</ins><span class="cx">                         var menu = this.frame.menu,
</span><span class="cx">                                 mode = this.get('menu'),
</span><span class="cx">                                 view;
</span><span class="lines">@@ -240,20 +301,48 @@
</span><span class="cx">                         if ( ! mode )
</span><span class="cx">                                 return;
</span><span class="cx"> 
</span><del>-                        if ( menu.mode() !== mode )
-                                menu.mode( mode );
</del><ins>+                        menu.mode( mode );
</ins><span class="cx"> 
</span><del>-                        view = menu.view();
</del><ins>+                        view = menu.get();
</ins><span class="cx">                         if ( view.select )
</span><span class="cx">                                 view.select( this.id );
</span><ins>+                },
+
+                _updateMenu: function() {
+                        var previous = this.previous('menu'),
+                                menu = this.get('menu');
+
+                        if ( previous )
+                                this.frame.off( 'menu:render:' + previous, this._renderMenu, this );
+
+                        if ( menu )
+                                this.frame.on( 'menu:render:' + menu, this._renderMenu, this );
+                },
+
+                _renderMenu: function( view ) {
+                        var menuItem = this.get('menuItem'),
+                                title = this.get('title'),
+                                priority = this.get('priority');
+
+                        if ( ! menuItem &amp;&amp; title ) {
+                                menuItem = { text: title };
+
+                                if ( priority )
+                                        menuItem.priority = priority;
+                        }
+
+                        if ( ! menuItem )
+                                return;
+
+                        view.set( this.id, menuItem );
</ins><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><span class="cx">         _.each(['toolbar','content'], function( region ) {
</span><del>-                media.controller.State.prototype[ region ] = function() {
</del><ins>+                media.controller.State.prototype[ '_' + region ] = function() {
</ins><span class="cx">                         var mode = this.get( region );
</span><span class="cx">                         if ( mode )
</span><del>-                                this.frame[ region ].mode( mode );
</del><ins>+                                this.frame[ region ].render( mode );
</ins><span class="cx">                 };
</span><span class="cx">         });
</span><span class="cx"> 
</span><span class="lines">@@ -262,15 +351,22 @@
</span><span class="cx">         media.controller.Library = media.controller.State.extend({
</span><span class="cx">                 defaults: {
</span><span class="cx">                         id:         'library',
</span><del>-                        multiple:   false,
</del><ins>+                        multiple:   false, // false, 'add', 'reset'
</ins><span class="cx">                         describe:   false,
</span><del>-                        toolbar:    'main-attachments',
</del><ins>+                        toolbar:    'select',
</ins><span class="cx">                         sidebar:    'settings',
</span><del>-                        content:    'browse',
</del><ins>+                        content:    'upload',
+                        router:     'browse',
</ins><span class="cx">                         searchable: true,
</span><span class="cx">                         filterable: false,
</span><del>-                        uploads:    true,
-                        sortable:   true
</del><ins>+                        sortable:   true,
+                        title:      l10n.mediaLibraryTitle,
+
+                        // Uses a user setting to override the content mode.
+                        contentUserSetting: true,
+
+                        // Sync the selection from the last state when 'multiple' matches.
+                        syncLastSelection: true
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><span class="lines">@@ -290,31 +386,37 @@
</span><span class="cx">                                 this.set( 'gutter', 8 );
</span><span class="cx"> 
</span><span class="cx">                         this.resetDisplays();
</span><del>-
-                        media.controller.State.prototype.initialize.apply( this, arguments );
</del><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 activate: function() {
</span><span class="cx">                         var library = this.get('library'),
</span><del>-                                selection = this.get('selection');
</del><ins>+                                selection = this.get('selection'),
+                                mode;
</ins><span class="cx"> 
</span><ins>+                        if ( this.get('syncLastSelection') ) {
+                                this.getLastSelection();
+                        }
+
</ins><span class="cx">                         this._excludeStateLibrary();
</span><span class="cx">                         this.buildComposite();
</span><span class="cx">                         this.on( 'change:library change:exclude', this.buildComposite, this );
</span><span class="cx">                         this.on( 'change:excludeState', this._excludeState, this );
</span><span class="cx"> 
</span><del>-                        // If we're in a workflow that supports multiple attachments,
-                        // automatically select any uploading attachments.
-                        if ( this.get('multiple') )
-                                wp.Uploader.queue.on( 'add', this.selectUpload, this );
</del><ins>+                        wp.Uploader.queue.on( 'add', this.uploading, this );
</ins><span class="cx"> 
</span><span class="cx">                         selection.on( 'add remove reset', this.refreshSelection, this );
</span><span class="cx"> 
</span><del>-                        this.refresh();
</del><span class="cx">                         this.on( 'insert', this._insertDisplaySettings, this );
</span><ins>+
+                        if ( this.get('contentUserSetting') ) {
+                                this.frame.on( 'content:activate', this.saveContentMode, this );
+                                this.set( 'content', getUserSetting( 'libraryContent', this.get('content') ) );
+                        }
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 deactivate: function() {
</span><ins>+                        this.frame.off( 'content:activate', this.saveContentMode, this );
+
</ins><span class="cx">                         // Unbind all event handlers that use this state as the context
</span><span class="cx">                         // from the selection.
</span><span class="cx">                         this.get('selection').off( null, null, this );
</span><span class="lines">@@ -330,13 +432,9 @@
</span><span class="cx">                 reset: function() {
</span><span class="cx">                         this.get('selection').reset();
</span><span class="cx">                         this.resetDisplays();
</span><ins>+                        this.refreshContent();
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                refresh: function() {
-                        this.content();
-                        this.refreshSelection();
-                },
-
</del><span class="cx">                 resetDisplays: function() {
</span><span class="cx">                         this._displays = [];
</span><span class="cx">                         this._defaultDisplaySettings = {
</span><span class="lines">@@ -371,19 +469,66 @@
</span><span class="cx">                         setUserSetting( 'urlbutton', display.link );
</span><span class="cx">                 },
</span><span class="cx"> 
</span><ins>+                getLastSelection: function() {
+                        var selection = this.get('selection'),
+                                lastState = this.frame.lastState(),
+                                lastSelection = lastState &amp;&amp; lastState.get('selection'),
+                                lastMultiple, thisMultiple;
+
+                        if ( ! lastSelection )
+                                return;
+
+                        // We don't care about the method of multiple selection the
+                        // selections use, just that they both support (or don't support)
+                        // multiple selection.
+                        lastMultiple = !! lastSelection.multiple;
+                        thisMultiple = !! selection.multiple;
+
+                        if ( lastMultiple !== thisMultiple )
+                                return;
+
+                        selection.reset( lastSelection.toArray() ).single( lastSelection.single() );
+                },
+
</ins><span class="cx">                 refreshSelection: function() {
</span><ins>+                        this.frame.toolbar.get().refresh();
+                        this.trigger( 'refresh:selection', this, this.get('selection') );
+                        this.refreshContent();
+                },
+
+                refreshContent: function() {
</ins><span class="cx">                         var selection = this.get('selection'),
</span><del>-                                mode = this.frame.content.mode();
</del><ins>+                                frame = this.frame,
+                                router = frame.router.get(),
+                                mode = frame.content.mode();
</ins><span class="cx"> 
</span><del>-                        this.frame.toolbar.view().refresh();
-                        this.trigger( 'refresh:selection', this, selection );
</del><ins>+                        if ( this.active&amp;&amp; ! selection.length &amp;&amp; ! router.get( mode ) )
+                                this.frame.content.render( this.get('content') );
+                },
</ins><span class="cx"> 
</span><del>-                        if ( ! selection.length &amp;&amp; 'browse' !== mode &amp;&amp; 'upload' !== mode )
-                                this.content();
</del><ins>+                uploading: function( attachment ) {
+                        var content = this.frame.content;
+
+                        // If the uploader was selected, navigate to the browser.
+                        if ( 'upload' === content.mode() )
+                                this.frame.content.mode('browse');
+
+                        // If we're in a workflow that supports multiple attachments,
+                        // automatically select any uploading attachments.
+                        if ( this.get('multiple') )
+                                this.get('selection').add( attachment );
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                selectUpload: function( attachment ) {
-                        this.get('selection').add( attachment );
</del><ins>+                saveContentMode: function() {
+                        // Only track the browse router on library states.
+                        if ( 'browse' !== this.get('router') )
+                                return;
+
+                        var mode = this.frame.content.mode(),
+                                view = this.frame.router.get();
+
+                        if ( view &amp;&amp; view.get( mode ) )
+                                setUserSetting( 'libraryContent', mode );
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 buildComposite: function() {
</span><span class="lines">@@ -448,45 +593,9 @@
</span><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><del>-
-        // wp.media.controller.Upload
-        // ---------------------------
-        media.controller.Upload = media.controller.State.extend({
-                defaults: _.defaults({
-                        id:      'upload',
-                        content: 'upload',
-                        toolbar: 'empty',
-                        uploads: true,
-
-                        // The state to navigate to when files are uploading.
-                        libraryState: 'library'
-                }, media.controller.State.prototype.defaults ),
-
-                initialize: function() {
-                        media.controller.State.prototype.initialize.apply( this, arguments );
-                },
-
-                activate: function() {
-                        wp.Uploader.queue.on( 'add', this.uploading, this );
-                        media.controller.State.prototype.activate.apply( this, arguments );
-                },
-
-                deactivate: function() {
-                        wp.Uploader.queue.off( null, null, this );
-                        media.controller.State.prototype.deactivate.apply( this, arguments );
-                },
-
-                uploading: function( attachment ) {
-                        var library = this.get('libraryState');
-
-                        this.frame.state( library ).get('selection').add( attachment );
-                        this.frame.setState( library );
-                }
-        });
-
-        // wp.media.controller.Gallery
-        // ---------------------------
-        media.controller.Gallery = media.controller.Library.extend({
</del><ins>+        // wp.media.controller.GalleryEdit
+        // -------------------------------
+        media.controller.GalleryEdit = media.controller.Library.extend({
</ins><span class="cx">                 defaults: {
</span><span class="cx">                         id:         'gallery-edit',
</span><span class="cx">                         multiple:   false,
</span><span class="lines">@@ -496,7 +605,10 @@
</span><span class="cx">                         sortable:   true,
</span><span class="cx">                         searchable: false,
</span><span class="cx">                         toolbar:    'gallery-edit',
</span><del>-                        content:    'browse'
</del><ins>+                        content:    'browse',
+                        title:      l10n.editGalleryTitle,
+                        priority:   60,
+                        dragInfo:   true
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><span class="lines">@@ -519,7 +631,7 @@
</span><span class="cx">                         // Watch for uploaded attachments.
</span><span class="cx">                         this.get('library').observe( wp.Uploader.queue );
</span><span class="cx"> 
</span><del>-                        this.frame.content.on( 'activate:browse', this.gallerySettings, this );
</del><ins>+                        this.frame.on( 'content:render:browse', this.gallerySettings, this );
</ins><span class="cx"> 
</span><span class="cx">                         media.controller.Library.prototype.activate.apply( this, arguments );
</span><span class="cx">                 },
</span><span class="lines">@@ -528,21 +640,19 @@
</span><span class="cx">                         // Stop watching for uploaded attachments.
</span><span class="cx">                         this.get('library').unobserve( wp.Uploader.queue );
</span><span class="cx"> 
</span><del>-                        this.frame.content.off( null, null, this );
</del><ins>+                        this.frame.off( 'content:render:browse', this.gallerySettings, this );
+
</ins><span class="cx">                         media.controller.Library.prototype.deactivate.apply( this, arguments );
</span><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                gallerySettings: function() {
-                        var library = this.get('library'),
-                                browser;
</del><ins>+                gallerySettings: function( browser ) {
+                        var library = this.get('library');
</ins><span class="cx"> 
</span><del>-                        if ( ! library )
</del><ins>+                        if ( ! library || ! browser )
</ins><span class="cx">                                 return;
</span><span class="cx"> 
</span><span class="cx">                         library.gallery = library.gallery || new Backbone.Model();
</span><span class="cx"> 
</span><del>-                        browser = this.frame.content.view();
-
</del><span class="cx">                         browser.sidebar.set({
</span><span class="cx">                                 gallery: new media.view.Settings.Gallery({
</span><span class="cx">                                         controller: this,
</span><span class="lines">@@ -570,7 +680,9 @@
</span><span class="cx">                         filterable: 'uploaded',
</span><span class="cx">                         multiple:   false,
</span><span class="cx">                         menu:       'main',
</span><del>-                        toolbar:    'featured-image'
</del><ins>+                        toolbar:    'featured-image',
+                        title:      l10n.featuredImageTitle,
+                        priority:   60
</ins><span class="cx">                 }, media.controller.Library.prototype.defaults ),
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><span class="lines">@@ -629,7 +741,10 @@
</span><span class="cx">                         menu:    'main',
</span><span class="cx">                         content: 'embed',
</span><span class="cx">                         toolbar: 'main-embed',
</span><del>-                        type:    'link'
</del><ins>+                        type:    'link',
+
+                        title:    l10n.fromUrlTitle,
+                        priority: 120
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 // The amount of time used when debouncing the scan.
</span><span class="lines">@@ -637,9 +752,9 @@
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><span class="cx">                         this.debouncedScan = _.debounce( _.bind( this.scan, this ), this.sensitivity );
</span><del>-                        this.on( 'change:url', this.debouncedScan, this );
</del><ins>+                        this.props = new Backbone.Model({ url: '' });
+                        this.props.on( 'change:url', this.debouncedScan, this );
</ins><span class="cx">                         this.on( 'scan', this.scanImage, this );
</span><del>-                        media.controller.State.prototype.initialize.apply( this, arguments );
</del><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 scan: function() {
</span><span class="lines">@@ -652,11 +767,11 @@
</span><span class="cx">                 scanImage: function( attributes ) {
</span><span class="cx">                         var frame = this.frame,
</span><span class="cx">                                 state = this,
</span><del>-                                url = this.get('url'),
</del><ins>+                                url = this.props.get('url'),
</ins><span class="cx">                                 image = new Image();
</span><span class="cx"> 
</span><span class="cx">                         image.onload = function() {
</span><del>-                                if ( state !== frame.state() || url !== state.get('url') )
</del><ins>+                                if ( state !== frame.state() || url !== state.props.get('url') )
</ins><span class="cx">                                         return;
</span><span class="cx"> 
</span><span class="cx">                                 state.set({
</span><span class="lines">@@ -670,14 +785,10 @@
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 reset: function() {
</span><del>-                        _.each( _.difference( _.keys( this.attributes ), _.keys( this.defaults ) ), function( key ) {
-                                this.unset( key );
-                        }, this );
</del><ins>+                        this.props = new Backbone.Model({ url: '' });
</ins><span class="cx"> 
</span><del>-                        this.set( 'url', '' );
-
</del><span class="cx">                         if ( this.id === this.frame.state().id )
</span><del>-                                this.frame.toolbar.view().refresh();
</del><ins>+                                this.frame.toolbar.get().refresh();
</ins><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><span class="lines">@@ -1022,9 +1133,13 @@
</span><span class="cx">                 // The constructor for the `Views` manager.
</span><span class="cx">                 Views: media.Views,
</span><span class="cx"> 
</span><del>-                constructor: function() {
</del><ins>+                constructor: function( options ) {
</ins><span class="cx">                         this.views = new this.Views( this, this.views );
</span><span class="cx">                         this.on( 'ready', this.ready, this );
</span><ins>+
+                        if ( options &amp;&amp; options.controller )
+                                this.controller = options.controller;
+
</ins><span class="cx">                         Backbone.View.apply( this, arguments );
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="lines">@@ -1097,9 +1212,9 @@
</span><span class="cx">                         // Initialize regions.
</span><span class="cx">                         _.each( this.regions, function( region ) {
</span><span class="cx">                                 this[ region ] = new media.controller.Region({
</span><del>-                                        controller: this,
-                                        id:         region,
-                                        selector:   '.media-frame-' + region
</del><ins>+                                        view:     this,
+                                        id:       region,
+                                        selector: '.media-frame-' + region
</ins><span class="cx">                                 });
</span><span class="cx">                         }, this );
</span><span class="cx">                 },
</span><span class="lines">@@ -1113,6 +1228,7 @@
</span><span class="cx">                         // Ensure states have a reference to the frame.
</span><span class="cx">                         this.states.on( 'add', function( model ) {
</span><span class="cx">                                 model.frame = this;
</span><ins>+                                model.trigger('ready');
</ins><span class="cx">                         }, this );
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="lines">@@ -1131,7 +1247,7 @@
</span><span class="cx">         media.view.MediaFrame = media.view.Frame.extend({
</span><span class="cx">                 className: 'media-frame',
</span><span class="cx">                 template:  media.template('media-frame'),
</span><del>-                regions:   ['menu','content','toolbar'],
</del><ins>+                regions:   ['menu','title','content','toolbar','router'],
</ins><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><span class="cx">                         media.view.Frame.prototype.initialize.apply( this, arguments );
</span><span class="lines">@@ -1173,6 +1289,10 @@
</span><span class="cx">                         }
</span><span class="cx"> 
</span><span class="cx">                         this.on( 'attach', _.bind( this.views.ready, this.views ), this );
</span><ins>+
+                        // Bind default title creation.
+                        this.on( 'title:create:default', this.createTitle, this );
+                        this.title.mode('default');
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 render: function() {
</span><span class="lines">@@ -1183,6 +1303,31 @@
</span><span class="cx">                         return media.view.Frame.prototype.render.apply( this, arguments );
</span><span class="cx">                 },
</span><span class="cx"> 
</span><ins>+                createTitle: function( title ) {
+                        title.view = new media.View({
+                                controller: this,
+                                tagName: 'h1'
+                        });
+                },
+
+                createMenu: function( menu ) {
+                        menu.view = new media.view.Menu({
+                                controller: this
+                        });
+                },
+
+                createToolbar: function( toolbar ) {
+                        menu.view = new media.view.Toolbar({
+                                controller: this
+                        });
+                },
+
+                createRouter: function( router ) {
+                        router.view = new media.view.Router({
+                                controller: this
+                        });
+                },
+
</ins><span class="cx">                 createIframeStates: function( options ) {
</span><span class="cx">                         var settings = media.view.settings,
</span><span class="cx">                                 tabs = settings.tabs,
</span><span class="lines">@@ -1208,22 +1353,25 @@
</span><span class="cx">                                 }, options ) );
</span><span class="cx">                         }, this );
</span><span class="cx"> 
</span><del>-                        this.content.on( 'activate:iframe', this.iframeContent, this );
-                        this.menu.on( 'activate:main', this.iframeMenu, this );
</del><ins>+                        this.on( 'content:create:iframe', this.iframeContent, this );
+                        this.on( 'menu:render:main', this.iframeMenu, this );
</ins><span class="cx">                         this.on( 'open', this.hijackThickbox, this );
</span><span class="cx">                         this.on( 'close', this.restoreThickbox, this );
</span><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                iframeContent: function() {
</del><ins>+                iframeContent: function( content ) {
</ins><span class="cx">                         this.$el.addClass('hide-toolbar');
</span><del>-                        this.content.view( new media.view.Iframe({
</del><ins>+                        content.view = new media.view.Iframe({
</ins><span class="cx">                                 controller: this
</span><del>-                        }).render() );
</del><ins>+                        });
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                iframeMenu: function() {
</del><ins>+                iframeMenu: function( view ) {
</ins><span class="cx">                         var views = {};
</span><span class="cx"> 
</span><ins>+                        if ( ! view )
+                                return;
+
</ins><span class="cx">                         _.each( media.view.settings.tabs, function( title, id ) {
</span><span class="cx">                                 views[ 'iframe:' + id ] = {
</span><span class="cx">                                         text: this.state( 'iframe:' + id ).get('title'),
</span><span class="lines">@@ -1231,7 +1379,7 @@
</span><span class="cx">                                 };
</span><span class="cx">                         }, this );
</span><span class="cx"> 
</span><del>-                        this.menu.view().set( views );
</del><ins>+                        view.set( views );
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 hijackThickbox: function() {
</span><span class="lines">@@ -1305,83 +1453,77 @@
</span><span class="cx">                                 new media.controller.Library({
</span><span class="cx">                                         selection: options.selection,
</span><span class="cx">                                         library:   media.query( options.library ),
</span><del>-                                        multiple:  this.options.multiple,
</del><ins>+                                        multiple:  options.multiple,
</ins><span class="cx">                                         menu:      'main',
</span><del>-                                        toolbar:   'select'
-                                }),
-
-                                new media.controller.Upload({
-                                        menu: 'main'
</del><ins>+                                        title:     options.title,
+                                        priority:  20
</ins><span class="cx">                                 })
</span><span class="cx">                         ]);
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 bindHandlers: function() {
</span><del>-                        this.menu.on( 'activate:main', this.mainMenu, this );
-                        this.content.on( 'activate:browse', this.browseContent, this );
-                        this.content.on( 'activate:upload', this.uploadContent, this );
-                        this.toolbar.on( 'activate:select', this.selectToolbar, this );
</del><ins>+                        this.on( 'menu:create:main', this.createMenu, this );
+                        this.on( 'router:create:browse', this.createRouter, this );
+                        this.on( 'router:render:browse', this.browseRouter, this );
+                        this.on( 'content:create:browse', this.browseContent, this );
+                        this.on( 'content:render:upload', this.uploadContent, this );
+                        this.on( 'toolbar:create:select', this.createSelectToolbar, this );
</ins><span class="cx"> 
</span><span class="cx">                         this.on( 'refresh:selection', this.refreshSelectToolbar, this );
</span><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                mainMenu: function( options ) {
-                        this.menu.view( new media.view.Menu({
-                                controller: this,
-                                silent:     options &amp;&amp; options.silent,
-
-                                views: {
-                                        upload: {
-                                                text: l10n.uploadFilesTitle,
-                                                priority: 20
-                                        },
-                                        library: {
-                                                text: l10n.mediaLibraryTitle,
-                                                priority: 40
-                                        }
</del><ins>+                // Routers
+                browseRouter: function( view ) {
+                        view.set({
+                                upload: {
+                                        text:     l10n.uploadFilesTitle,
+                                        priority: 20
+                                },
+                                browse: {
+                                        text:     l10n.mediaLibraryTitle,
+                                        priority: 40
</ins><span class="cx">                                 }
</span><del>-                        }) );
</del><ins>+                        });
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 // Content
</span><del>-                browseContent: function() {
</del><ins>+                browseContent: function( content ) {
</ins><span class="cx">                         var state = this.state();
</span><span class="cx"> 
</span><span class="cx">                         this.$el.removeClass('hide-toolbar');
</span><span class="cx"> 
</span><span class="cx">                         // Browse our library of attachments.
</span><del>-                        this.content.view( new media.view.AttachmentsBrowser({
</del><ins>+                        content.view = new media.view.AttachmentsBrowser({
</ins><span class="cx">                                 controller: this,
</span><span class="cx">                                 collection: state.get('library'),
</span><span class="cx">                                 selection:  state.get('selection'),
</span><span class="cx">                                 model:      state,
</span><span class="cx">                                 sortable:   state.get('sortable'),
</span><span class="cx">                                 search:     state.get('searchable'),
</span><del>-                                uploads:    state.get('uploads'),
</del><span class="cx">                                 filters:    state.get('filterable'),
</span><span class="cx">                                 display:    state.get('displaySettings'),
</span><ins>+                                dragInfo:   state.get('dragInfo'),
</ins><span class="cx"> 
</span><span class="cx">                                 AttachmentView: state.get('AttachmentView')
</span><del>-                        }) );
</del><ins>+                        });
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 uploadContent: function() {
</span><del>-                        this.$el.addClass('hide-toolbar');
-
-                        this.content.view( new media.view.UploaderInline({
</del><ins>+                        this.$el.removeClass('hide-toolbar');
+                        this.content.set( new media.view.UploaderInline({
</ins><span class="cx">                                 controller: this
</span><span class="cx">                         }) );
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 // Toolbars
</span><del>-                selectToolbar: function( options ) {
</del><ins>+                createSelectToolbar: function( toolbar, options ) {
</ins><span class="cx">                         options = _.defaults( options || {}, {
</span><span class="cx">                                 event:  'select',
</span><span class="cx">                                 silent: false,
</span><span class="cx">                                 state:  false
</span><span class="cx">                         });
</span><span class="cx"> 
</span><del>-                        this.toolbar.view( new media.view.Toolbar({
</del><ins>+                        toolbar.view = new media.view.Toolbar({
</ins><span class="cx">                                 controller: this,
</span><span class="cx">                                 silent:     options.silent,
</span><span class="cx"> 
</span><span class="lines">@@ -1402,7 +1544,7 @@
</span><span class="cx">                                                 }
</span><span class="cx">                                         }
</span><span class="cx">                                 }
</span><del>-                        }) );
</del><ins>+                        });
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 refreshSelectToolbar: function() {
</span><span class="lines">@@ -1411,7 +1553,7 @@
</span><span class="cx">                         if ( ! selection || 'select' !== this.toolbar.mode() )
</span><span class="cx">                                 return;
</span><span class="cx"> 
</span><del>-                        this.toolbar.view().get('select').model.set( 'disabled', ! selection.length );
</del><ins>+                        this.toolbar.get().get('select').model.set( 'disabled', ! selection.length );
</ins><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><span class="lines">@@ -1430,18 +1572,23 @@
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 createStates: function() {
</span><del>-                        var options = this.options;
</del><ins>+                        var options = this.options,
+                                selection = options.selection;
</ins><span class="cx"> 
</span><span class="cx">                         // Add the default states.
</span><span class="cx">                         this.states.add([
</span><span class="cx">                                 // Main states.
</span><span class="cx">                                 new media.controller.Library({
</span><del>-                                        selection:  options.selection,
</del><ins>+                                        id:         'insert',
+                                        title:      l10n.insertMediaTitle,
+                                        priority:   20,
+                                        menu:       'main',
+                                        toolbar:    'main-insert',
+                                        filterable: 'all',
</ins><span class="cx">                                         library:    media.query( options.library ),
</span><ins>+                                        selection:  selection,
+                                        multiple:   options.multiple ? 'reset' : false,
</ins><span class="cx">                                         editable:   true,
</span><del>-                                        filterable: 'all',
-                                        multiple:   this.options.multiple,
-                                        menu:       'main',
</del><span class="cx"> 
</span><span class="cx">                                         // Show the attachment display settings.
</span><span class="cx">                                         displaySettings: true,
</span><span class="lines">@@ -1450,15 +1597,30 @@
</span><span class="cx">                                         displayUserSettings: true
</span><span class="cx">                                 }),
</span><span class="cx"> 
</span><del>-                                new media.controller.Upload({
-                                        menu: 'main'
</del><ins>+                                new media.controller.Library({
+                                        id:         'gallery',
+                                        title:      l10n.createGalleryTitle,
+                                        priority:   40,
+                                        menu:       'main',
+                                        toolbar:    'main-gallery',
+                                        filterable: 'uploaded',
+                                        multiple:   'add',
+                                        editable:   true,
+
+                                        library:  media.query( _.defaults({
+                                                type: 'image'
+                                        }, options.library ) ),
+
+                                        selection: new media.model.Selection( selection.models, {
+                                                multiple: 'add'
+                                        })
</ins><span class="cx">                                 }),
</span><span class="cx"> 
</span><span class="cx">                                 // Embed states.
</span><span class="cx">                                 new media.controller.Embed(),
</span><span class="cx"> 
</span><span class="cx">                                 // Gallery states.
</span><del>-                                new media.controller.Gallery({
</del><ins>+                                new media.controller.GalleryEdit({
</ins><span class="cx">                                         library: options.selection,
</span><span class="cx">                                         editing: options.editing,
</span><span class="cx">                                         menu:    'gallery'
</span><span class="lines">@@ -1468,16 +1630,12 @@
</span><span class="cx">                                         id:           'gallery-library',
</span><span class="cx">                                         library:      media.query({ type: 'image' }),
</span><span class="cx">                                         filterable:   'uploaded',
</span><del>-                                        multiple:     true,
</del><ins>+                                        multiple:     'add',
</ins><span class="cx">                                         menu:         'gallery',
</span><span class="cx">                                         toolbar:      'gallery-add',
</span><del>-                                        excludeState: 'gallery-edit'
-                                }),
-
-                                new media.controller.Upload({
-                                        id:           'gallery-upload',
-                                        menu:         'gallery',
-                                        libraryState: 'gallery-edit'
</del><ins>+                                        excludeState: 'gallery-edit',
+                                        title:        l10n.addToGalleryTitle,
+                                        priority:     100
</ins><span class="cx">                                 })
</span><span class="cx">                         ]);
</span><span class="cx"> 
</span><span class="lines">@@ -1492,9 +1650,13 @@
</span><span class="cx"> 
</span><span class="cx">                 bindHandlers: function() {
</span><span class="cx">                         media.view.MediaFrame.Select.prototype.bindHandlers.apply( this, arguments );
</span><ins>+                        this.on( 'menu:create:gallery', this.createMenu, this );
+                        this.on( 'toolbar:create:main-insert', this.createSelectionToolbar, this );
+                        this.on( 'toolbar:create:main-gallery', this.createSelectionToolbar, this );
</ins><span class="cx"> 
</span><span class="cx">                         var handlers = {
</span><span class="cx">                                         menu: {
</span><ins>+                                                'main':    'mainMenu',
</ins><span class="cx">                                                 'gallery': 'galleryMenu'
</span><span class="cx">                                         },
</span><span class="cx"> 
</span><span class="lines">@@ -1504,7 +1666,8 @@
</span><span class="cx">                                         },
</span><span class="cx"> 
</span><span class="cx">                                         toolbar: {
</span><del>-                                                'main-attachments': 'mainAttachmentsToolbar',
</del><ins>+                                                'main-insert':      'mainInsertToolbar',
+                                                'main-gallery':     'mainGalleryToolbar',
</ins><span class="cx">                                                 'main-embed':       'mainEmbedToolbar',
</span><span class="cx">                                                 'featured-image':   'featuredImageToolbar',
</span><span class="cx">                                                 'gallery-edit':     'galleryEditToolbar',
</span><span class="lines">@@ -1514,70 +1677,42 @@
</span><span class="cx"> 
</span><span class="cx">                         _.each( handlers, function( regionHandlers, region ) {
</span><span class="cx">                                 _.each( regionHandlers, function( callback, handler ) {
</span><del>-                                        this[ region ].on( 'activate:' + handler, this[ callback ], this );
</del><ins>+                                        this.on( region + ':render:' + handler, this[ callback ], this );
</ins><span class="cx">                                 }, this );
</span><span class="cx">                         }, this );
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 // Menus
</span><del>-                mainMenu: function() {
-                        media.view.MediaFrame.Select.prototype.mainMenu.call( this, { silent: true });
-
-                        this.menu.view().set({
</del><ins>+                mainMenu: function( view ) {
+                        view.set({
</ins><span class="cx">                                 'library-separator': new media.View({
</span><span class="cx">                                         className: 'separator',
</span><del>-                                        priority: 60
-                                }),
-                                'embed': {
-                                        text: l10n.fromUrlTitle,
-                                        priority: 80
-                                }
</del><ins>+                                        priority: 100
+                                })
</ins><span class="cx">                         });
</span><del>-
-                        if ( media.view.settings.post.featuredImageId ) {
-                                this.menu.view().set( 'featured-image', {
-                                        text: l10n.featuredImageTitle,
-                                        priority: 100
-                                });
-                        }
</del><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                galleryMenu: function() {
</del><ins>+                galleryMenu: function( view ) {
</ins><span class="cx">                         var lastState = this.lastState(),
</span><span class="cx">                                 previous = lastState &amp;&amp; lastState.id,
</span><span class="cx">                                 frame = this;
</span><span class="cx"> 
</span><del>-                        this.menu.view( new media.view.Menu({
-                                controller: this,
-                                views: {
-                                        cancel: {
-                                                text:     l10n.cancelGalleryTitle,
-                                                priority: 20,
-                                                click:    function() {
-                                                        if ( previous )
-                                                                frame.setState( previous );
-                                                        else
-                                                                frame.close();
-                                                }
-                                        },
-                                        separateCancel: new media.View({
-                                                className: 'separator',
-                                                priority: 40
-                                        }),
-                                        'gallery-edit': {
-                                                text: l10n.editGalleryTitle,
-                                                priority: 60
-                                        },
-                                        'gallery-upload': {
-                                                text: l10n.uploadImagesTitle,
-                                                priority: 80
-                                        },
-                                        'gallery-library': {
-                                                text: l10n.mediaLibraryTitle,
-                                                priority: 100
</del><ins>+                        view.set({
+                                cancel: {
+                                        text:     l10n.cancelGalleryTitle,
+                                        priority: 20,
+                                        click:    function() {
+                                                if ( previous )
+                                                        frame.setState( previous );
+                                                else
+                                                        frame.close();
</ins><span class="cx">                                         }
</span><del>-                                }
-                        }) );
</del><ins>+                                },
+                                separateCancel: new media.View({
+                                        className: 'separator',
+                                        priority: 40
+                                })
+                        });
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 // Content
</span><span class="lines">@@ -1587,7 +1722,7 @@
</span><span class="cx">                                 model:      this.state()
</span><span class="cx">                         }).render();
</span><span class="cx"> 
</span><del>-                        this.content.view( view );
</del><ins>+                        this.content.set( view );
</ins><span class="cx">                         view.url.focus();
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="lines">@@ -1603,6 +1738,7 @@
</span><span class="cx">                                 model:      state,
</span><span class="cx">                                 sortable:   true,
</span><span class="cx">                                 search:     false,
</span><ins>+                                dragInfo:   true,
</ins><span class="cx"> 
</span><span class="cx">                                 AttachmentView: media.view.Attachment.EditSelection
</span><span class="cx">                         }).render();
</span><span class="lines">@@ -1617,37 +1753,62 @@
</span><span class="cx">                         });
</span><span class="cx"> 
</span><span class="cx">                         // Browse our library of attachments.
</span><del>-                        this.content.view( view );
</del><ins>+                        this.content.set( view );
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                // Sidebars
-                onSidebarGallerySettings: function( options ) {
-                        var library = this.state().get('library');
</del><ins>+                // Toolbars
+                createSelectionToolbar: function( toolbar ) {
+                        toolbar.view = new media.view.Toolbar.Selection({
+                                controller: this,
+                                editable:   this.state().get('editable')
+                        });
+                },
</ins><span class="cx"> 
</span><del>-                        if ( ! library )
-                                return;
</del><ins>+                mainInsertToolbar: function( view ) {
+                        var controller = this;
</ins><span class="cx"> 
</span><del>-                        library.gallery = library.gallery || new Backbone.Model();
</del><ins>+                        view.button = 'insert';
+                        view.set( 'insert', {
+                                style:    'primary',
+                                priority: 80,
+                                text:     l10n.insertIntoPost,
</ins><span class="cx"> 
</span><del>-                        this.sidebar.view().set({
-                                gallery: new media.view.Settings.Gallery({
-                                        controller: this,
-                                        model:      library.gallery,
-                                        priority:   40
-                                }).render()
-                        }, options );
</del><ins>+                                click: function() {
+                                        var state = controller.state(),
+                                                selection = state.get('selection');
+
+                                        controller.close();
+                                        state.trigger( 'insert', selection ).reset();
+                                }
+                        });
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                // Toolbars
-                mainAttachmentsToolbar: function() {
-                        this.toolbar.view( new media.view.Toolbar.Insert({
-                                controller: this,
-                                editable:   this.state().get('editable')
-                        }) );
</del><ins>+                mainGalleryToolbar: function( view ) {
+                        var controller = this;
+
+                        view.button = 'gallery';
+                        view.set( 'gallery', {
+                                style:    'primary',
+                                text:     l10n.createNewGallery,
+                                priority: 60,
+
+                                click: function() {
+                                        var selection = controller.state().get('selection'),
+                                                edit = controller.state('gallery-edit'),
+                                                models = selection.where({ type: 'image' });
+
+                                        edit.set( 'library', new media.model.Selection( models, {
+                                                props:    selection.props.toJSON(),
+                                                multiple: true
+                                        }) );
+
+                                        this.controller.setState('gallery-edit');
+                                }
+                        });
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 featuredImageToolbar: function() {
</span><del>-                        this.toolbar.view( new media.view.Toolbar.Select({
</del><ins>+                        this.toolbar.set( new media.view.Toolbar.Select({
</ins><span class="cx">                                 controller: this,
</span><span class="cx">                                 text:       l10n.setFeaturedImage,
</span><span class="cx">                                 state:      this.options.state || 'upload'
</span><span class="lines">@@ -1655,7 +1816,7 @@
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 mainEmbedToolbar: function() {
</span><del>-                        this.toolbar.view( new media.view.Toolbar.Embed({
</del><ins>+                        this.toolbar.set( new media.view.Toolbar.Embed({
</ins><span class="cx">                                 controller: this
</span><span class="cx">                         }) );
</span><span class="cx"> 
</span><span class="lines">@@ -1664,7 +1825,7 @@
</span><span class="cx"> 
</span><span class="cx">                 galleryEditToolbar: function() {
</span><span class="cx">                         var editing = this.state().get('editing');
</span><del>-                        this.toolbar.view( new media.view.Toolbar({
</del><ins>+                        this.toolbar.set( new media.view.Toolbar({
</ins><span class="cx">                                 controller: this,
</span><span class="cx">                                 items: {
</span><span class="cx">                                         insert: {
</span><span class="lines">@@ -1689,7 +1850,7 @@
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 galleryAddToolbar: function() {
</span><del>-                        this.toolbar.view( new media.view.Toolbar({
</del><ins>+                        this.toolbar.set( new media.view.Toolbar({
</ins><span class="cx">                                 controller: this,
</span><span class="cx">                                 items: {
</span><span class="cx">                                         insert: {
</span><span class="lines">@@ -1704,7 +1865,7 @@
</span><span class="cx"> 
</span><span class="cx">                                                         edit.get('library').add( state.get('selection').models );
</span><span class="cx">                                                         state.trigger('reset');
</span><del>-                                                        controller.state('gallery-edit');
</del><ins>+                                                        controller.setState('gallery-edit');
</ins><span class="cx">                                                 }
</span><span class="cx">                                         }
</span><span class="cx">                                 }
</span><span class="lines">@@ -1729,8 +1890,6 @@
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><del>-                        this.controller = this.options.controller;
-
</del><span class="cx">                         _.defaults( this.options, {
</span><span class="cx">                                 container: document.body,
</span><span class="cx">                                 title:     '',
</span><span class="lines">@@ -1838,8 +1997,6 @@
</span><span class="cx">                 initialize: function() {
</span><span class="cx">                         var uploader;
</span><span class="cx"> 
</span><del>-                        this.controller = this.options.controller;
-
</del><span class="cx">                         this.$browser = $('&lt;a href=&quot;#&quot; class=&quot;browser&quot; /&gt;').hide().appendTo('body');
</span><span class="cx"> 
</span><span class="cx">                         uploader = this.options.uploader = _.defaults( this.options.uploader || {}, {
</span><span class="lines">@@ -1906,7 +2063,10 @@
</span><span class="cx">                 template:  media.template('uploader-inline'),
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><del>-                        this.controller = this.options.controller;
</del><ins>+                        _.defaults( this.options, {
+                                message: '',
+                                status:  true
+                        });
</ins><span class="cx"> 
</span><span class="cx">                         if ( ! this.options.$browser &amp;&amp; this.controller.uploader )
</span><span class="cx">                                 this.options.$browser = this.controller.uploader.$browser;
</span><span class="lines">@@ -1914,9 +2074,11 @@
</span><span class="cx">                         if ( _.isUndefined( this.options.postId ) )
</span><span class="cx">                                 this.options.postId = media.view.settings.post.id;
</span><span class="cx"> 
</span><del>-                        this.views.set( '.upload-inline-status', new media.view.UploaderStatus({
-                                controller: this.controller
-                        }) );
</del><ins>+                        if ( this.options.status ) {
+                                this.views.set( '.upload-inline-status', new media.view.UploaderStatus({
+                                        controller: this.controller
+                                }) );
+                        }
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 ready: function() {
</span><span class="lines">@@ -1951,8 +2113,6 @@
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><del>-                        this.controller = this.options.controller;
-
</del><span class="cx">                         this.queue = wp.Uploader.queue;
</span><span class="cx">                         this.queue.on( 'add remove reset', this.visibility, this );
</span><span class="cx">                         this.queue.on( 'add remove reset change:percent', this.progress, this );
</span><span class="lines">@@ -2060,8 +2220,6 @@
</span><span class="cx">                 className: 'media-toolbar',
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><del>-                        this.controller = this.options.controller;
-
</del><span class="cx">                         this._views     = {};
</span><span class="cx">                         this.$primary   = $('&lt;div class=&quot;media-toolbar-primary&quot; /&gt;').prependTo( this.$el );
</span><span class="cx">                         this.$secondary = $('&lt;div class=&quot;media-toolbar-secondary&quot; /&gt;').prependTo( this.$el );
</span><span class="lines">@@ -2199,50 +2357,32 @@
</span><span class="cx">         // ---------------------------
</span><span class="cx">         media.view.Toolbar.Embed = media.view.Toolbar.Select.extend({
</span><span class="cx">                 initialize: function() {
</span><del>-                        var controller = this.options.controller;
-
</del><span class="cx">                         _.defaults( this.options, {
</span><span class="cx">                                 text: l10n.insertIntoPost
</span><span class="cx">                         });
</span><span class="cx"> 
</span><span class="cx">                         media.view.Toolbar.Select.prototype.initialize.apply( this, arguments );
</span><del>-                        controller.on( 'change:url', this.refresh, this );
</del><ins>+                        this.controller.state().props.on( 'change:url', this.refresh, this );
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 refresh: function() {
</span><del>-                        var url = this.controller.state().get('url');
</del><ins>+                        var url = this.controller.state().props.get('url');
</ins><span class="cx">                         this.get('select').model.set( 'disabled', ! url || /^https?:\/\/$/.test(url) );
</span><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><del>-        // wp.media.view.Toolbar.Insert
-        // ----------------------------
-        media.view.Toolbar.Insert = media.view.Toolbar.extend({
</del><ins>+        // wp.media.view.Toolbar.Selection
+        // -------------------------------
+        media.view.Toolbar.Selection = media.view.Toolbar.extend({
+                button: 'insert',
+
</ins><span class="cx">                 initialize: function() {
</span><del>-                        var controller = this.options.controller,
-                                selection = controller.state().get('selection'),
-                                selectionToLibrary;
</del><ins>+                        var controller = this.controller;
</ins><span class="cx"> 
</span><del>-                        selectionToLibrary = function( state, filter ) {
-                                return function() {
-                                        var controller = this.controller,
-                                                selection = controller.state().get('selection'),
-                                                edit = controller.state( state ),
-                                                models = filter ? filter( selection ) : selection.models;
-
-                                        edit.set( 'library', new media.model.Selection( models, {
-                                                props:    selection.props.toJSON(),
-                                                multiple: true
-                                        }) );
-
-                                        this.controller.setState( state );
-                                };
-                        };
-
</del><span class="cx">                         this.options.items = _.defaults( this.options.items || {}, {
</span><span class="cx">                                 selection: new media.view.Selection({
</span><span class="cx">                                         controller: controller,
</span><del>-                                        collection: selection,
</del><ins>+                                        collection: controller.state().get('selection'),
</ins><span class="cx">                                         priority:   -40,
</span><span class="cx"> 
</span><span class="cx">                                         // If the selection is editable, pass the callback to
</span><span class="lines">@@ -2250,26 +2390,7 @@
</span><span class="cx">                                         editable: this.options.editable &amp;&amp; function() {
</span><span class="cx">                                                 this.controller.content.mode('edit-selection');
</span><span class="cx">                                         }
</span><del>-                                }).render(),
-
-                                insert: {
-                                        style:    'primary',
-                                        priority: 80,
-                                        text:     l10n.insertIntoPost,
-
-                                        click: function() {
-                                                controller.close();
-                                                controller.state().trigger( 'insert', selection ).reset();
-                                        }
-                                },
-
-                                gallery: {
-                                        text:     l10n.createNewGallery,
-                                        priority: 40,
-                                        click:    selectionToLibrary('gallery-edit', function( selection ) {
-                                                return selection.where({ type: 'image' });
-                                        })
-                                }
</del><ins>+                                }).render()
</ins><span class="cx">                         });
</span><span class="cx"> 
</span><span class="cx">                         media.view.Toolbar.prototype.initialize.apply( this, arguments );
</span><span class="lines">@@ -2277,14 +2398,12 @@
</span><span class="cx"> 
</span><span class="cx">                 refresh: function() {
</span><span class="cx">                         var selection = this.controller.state().get('selection'),
</span><del>-                                count = selection.length;
</del><ins>+                                button = this.get( this.button );
</ins><span class="cx"> 
</span><del>-                        this.get('insert').model.set( 'disabled', ! selection.length );
</del><ins>+                        if ( ! button )
+                                return;
</ins><span class="cx"> 
</span><del>-                        // Check if any attachment in the selection is an image.
-                        this.get('gallery').$el.toggle( count &gt; 1 &amp;&amp; selection.any( function( attachment ) {
-                                return 'image' === attachment.get('type');
-                        }) );
</del><ins>+                        button.model.set( 'disabled', ! selection.length );
</ins><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><span class="lines">@@ -2388,8 +2507,7 @@
</span><span class="cx">                 tagName:   'div',
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><del>-                        this.controller = this.options.controller;
-                        this._views     = {};
</del><ins>+                        this._views = {};
</ins><span class="cx"> 
</span><span class="cx">                         this.set( _.extend( {}, this._views, this.options.views ), { silent: true });
</span><span class="cx">                         delete this.options.views;
</span><span class="lines">@@ -2457,23 +2575,95 @@
</span><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><ins>+        /**
+         * wp.media.view.MenuItem
+         */
+        media.view.MenuItem = media.View.extend({
+                tagName:   'a',
+                className: 'media-menu-item',
</ins><span class="cx"> 
</span><ins>+                attributes: {
+                        href: '#'
+                },
+
+                events: {
+                        'click': '_click'
+                },
+
+                _click: function( event ) {
+                        var clickOverride = this.options.click;
+
+                        if ( event )
+                                event.preventDefault();
+
+                        if ( clickOverride )
+                                clickOverride.call( this );
+                        else
+                                this.click();
+                },
+
+                click: function() {
+                        var state = this.options.state;
+                        if ( state )
+                                this.controller.setState( state );
+                },
+
+                render: function() {
+                        var options = this.options;
+
+                        if ( options.text )
+                                this.$el.text( options.text );
+                        else if ( options.html )
+                                this.$el.html( options.html );
+
+                        return this;
+                }
+        });
+
</ins><span class="cx">         /**
</span><span class="cx">          * wp.media.view.Menu
</span><span class="cx">          */
</span><span class="cx">         media.view.Menu = media.view.PriorityList.extend({
</span><del>-                tagName:   'ul',
</del><ins>+                tagName:   'div',
</ins><span class="cx">                 className: 'media-menu',
</span><ins>+                property:  'state',
+                ItemView:  media.view.MenuItem,
+                region:    'menu',
</ins><span class="cx"> 
</span><del>-                toView: function( options, state ) {
</del><ins>+                toView: function( options, id ) {
</ins><span class="cx">                         options = options || {};
</span><del>-                        options.state = options.state || state;
-                        return new media.view.MenuItem( options ).render();
</del><ins>+                        options[ this.property ] = options[ this.property ] || id;
+                        return new this.ItemView( options ).render();
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                select: function( state ) {
-                        var view = this.get( state );
</del><ins>+                ready: function() {
+                        media.view.PriorityList.prototype.ready.apply( this, arguments );
+                        this.visibility();
+                },
</ins><span class="cx"> 
</span><ins>+                set: function() {
+                        media.view.PriorityList.prototype.set.apply( this, arguments );
+                        this.visibility();
+                },
+
+                unset: function() {
+                        media.view.PriorityList.prototype.unset.apply( this, arguments );
+                        this.visibility();
+                },
+
+                visibility: function() {
+                        var region = this.region,
+                                view = this.controller[ region ].get(),
+                                views = this.views.get(),
+                                hide = ! views || views.length &lt; 2;
+
+                        if ( this === view )
+                                this.controller.$el.toggleClass( 'hide-' + region, hide );
+                },
+
+                select: function( id ) {
+                        var view = this.get( id );
+
</ins><span class="cx">                         if ( ! view )
</span><span class="cx">                                 return;
</span><span class="cx"> 
</span><span class="lines">@@ -2486,35 +2676,40 @@
</span><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><del>-        media.view.MenuItem = media.View.extend({
-                tagName:   'li',
-                className: 'media-menu-item',
</del><ins>+        /**
+         * wp.media.view.RouterItem
+         */
+        media.view.RouterItem = media.view.MenuItem.extend({
+                click: function() {
+                        var contentMode = this.options.contentMode;
+                        if ( contentMode )
+                                this.controller.content.mode( contentMode );
+                }
+        });
</ins><span class="cx"> 
</span><del>-                events: {
-                        'click': 'click'
-                },
</del><ins>+        /**
+         * wp.media.view.Router
+         */
+        media.view.Router = media.view.Menu.extend({
+                tagName:   'div',
+                className: 'media-router',
+                property:  'contentMode',
+                ItemView:  media.view.RouterItem,
+                region:    'router',
</ins><span class="cx"> 
</span><del>-                click: function() {
-                        var options = this.options;
-
-                        if ( options.click )
-                                options.click.call( this );
-                        else if ( options.state )
-                                this.controller.setState( options.state );
</del><ins>+                initialize: function() {
+                        this.controller.on( 'content:render', this.update, this );
+                        media.view.Menu.prototype.initialize.apply( this, arguments );
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                render: function() {
-                        var options = this.options;
-
-                        if ( options.text )
-                                this.$el.text( options.text );
-                        else if ( options.html )
-                                this.$el.html( options.html );
-
-                        return this;
</del><ins>+                update: function() {
+                        var mode = this.controller.content.mode();
+                        if ( mode )
+                                this.select( mode );
</ins><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">         /**
</span><span class="cx">          * wp.media.view.Sidebar
</span><span class="cx">          */
</span><span class="lines">@@ -2531,7 +2726,7 @@
</span><span class="cx">                 template:  media.template('attachment'),
</span><span class="cx"> 
</span><span class="cx">                 events: {
</span><del>-                        'click .attachment-preview':      'toggleSelection',
</del><ins>+                        'click .attachment-preview':      'toggleSelectionHandler',
</ins><span class="cx">                         'change [data-setting]':          'updateSetting',
</span><span class="cx">                         'change [data-setting] input':    'updateSetting',
</span><span class="cx">                         'change [data-setting] select':   'updateSetting',
</span><span class="lines">@@ -2546,8 +2741,6 @@
</span><span class="cx">                 initialize: function() {
</span><span class="cx">                         var selection = this.options.selection;
</span><span class="cx"> 
</span><del>-                        this.controller = this.options.controller;
-
</del><span class="cx">                         this.model.on( 'change:sizes change:uploading change:caption change:title', this.render, this );
</span><span class="cx">                         this.model.on( 'change:percent', this.progress, this );
</span><span class="cx"> 
</span><span class="lines">@@ -2623,20 +2816,70 @@
</span><span class="cx">                                 this.$bar.width( this.model.get('percent') + '%' );
</span><span class="cx">                 },
</span><span class="cx"> 
</span><del>-                toggleSelection: function( event ) {
-                        var selection = this.options.selection,
-                                model = this.model;
</del><ins>+                toggleSelectionHandler: function( event ) {
+                        var method;
</ins><span class="cx"> 
</span><ins>+                        if ( event.shiftKey )
+                                method = 'between';
+                        else if ( event.ctrlKey || event.metaKey )
+                                method = 'toggle';
+
+                        this.toggleSelection({
+                                method: method
+                        });
+                },
+
+                toggleSelection: function( options ) {
+                        var collection = this.collection,
+                                selection = this.options.selection,
+                                model = this.model,
+                                method = options &amp;&amp; options.method,
+                                single, between, models, singleIndex, modelIndex;
+
</ins><span class="cx">                         if ( ! selection )
</span><span class="cx">                                 return;
</span><span class="cx"> 
</span><ins>+                        single = selection.single();
+                        method = _.isUndefined( method ) ? selection.multiple : method;
+
+                        // If the `method` is set to `between`, select all models that
+                        // exist between the current and the selected model.
+                        if ( 'between' === method &amp;&amp; single &amp;&amp; selection.multiple ) {
+                                // If the models are the same, short-circuit.
+                                if ( single === model )
+                                        return;
+
+                                singleIndex = collection.indexOf( single );
+                                modelIndex  = collection.indexOf( this.model );
+
+                                if ( singleIndex &lt; modelIndex )
+                                        models = collection.models.slice( singleIndex, modelIndex + 1 );
+                                else
+                                        models = collection.models.slice( modelIndex, singleIndex + 1 );
+
+                                selection.add( models ).single( model );
+                                return;
+
+                        // If the `method` is set to `toggle`, just flip the selection
+                        // status, regardless of whether the model is the single model.
+                        } else if ( 'toggle' === method ) {
+                                selection[ this.selected() ? 'remove' : 'add' ]( model ).single( model );
+                                return;
+                        }
+
+                        if ( method !== 'add' )
+                                method = 'reset';
+
</ins><span class="cx">                         if ( this.selected() ) {
</span><span class="cx">                                 // If the model is the single model, remove it.
</span><span class="cx">                                 // If it is not the same as the single model,
</span><span class="cx">                                 // it now becomes the single model.
</span><del>-                                selection[ selection.single() === model ? 'remove' : 'single' ]( model );
</del><ins>+                                selection[ single === model ? 'remove' : 'single' ]( model );
</ins><span class="cx">                         } else {
</span><del>-                                selection.add( model ).single( model );
</del><ins>+                                // If the model is not selected, run the `method` on the
+                                // selection. By default, we `reset` the selection, but the
+                                // `method` can be set to `add` the model to the selection.
+                                selection[ method ]( model ).single( model );
</ins><span class="cx">                         }
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="lines">@@ -2838,7 +3081,6 @@
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><del>-                        this.controller = this.options.controller;
</del><span class="cx">                         this.el.id = _.uniqueId('__attachments-view-');
</span><span class="cx"> 
</span><span class="cx">                         _.defaults( this.options, {
</span><span class="lines">@@ -2950,13 +3192,16 @@
</span><span class="cx">                                         collection.remove( model, {
</span><span class="cx">                                                 silent: true
</span><span class="cx">                                         }).add( model, {
</span><del>-                                                at:     ui.item.index(),
-                                                silent: true
</del><ins>+                                                silent: true,
+                                                at:     ui.item.index()
</ins><span class="cx">                                         });
</span><span class="cx"> 
</span><span class="cx">                                         // Restore the comparator.
</span><span class="cx">                                         collection.comparator = comparator;
</span><span class="cx"> 
</span><ins>+                                        // Fire the `reset` event to ensure other collections sync.
+                                        collection.trigger( 'reset', collection );
+
</ins><span class="cx">                                         // If the collection is sorted by menu order,
</span><span class="cx">                                         // update the menu order.
</span><span class="cx">                                         collection.saveMenuOrder();
</span><span class="lines">@@ -3200,12 +3445,9 @@
</span><span class="cx">                 className: 'attachments-browser',
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><del>-                        this.controller = this.options.controller;
-
</del><span class="cx">                         _.defaults( this.options, {
</span><span class="cx">                                 filters: false,
</span><span class="cx">                                 search:  true,
</span><del>-                                uploads: false,
</del><span class="cx">                                 display: false,
</span><span class="cx"> 
</span><span class="cx">                                 AttachmentView: media.view.Attachment.Library
</span><span class="lines">@@ -3255,7 +3497,7 @@
</span><span class="cx">                                 }).render() );
</span><span class="cx">                         }
</span><span class="cx"> 
</span><del>-                        if ( this.options.sortable &amp;&amp; ! this.options.filters ) {
</del><ins>+                        if ( this.options.dragInfo ) {
</ins><span class="cx">                                 this.toolbar.set( 'dragInfo', new media.View({
</span><span class="cx">                                         el: $( '&lt;div class=&quot;instructions&quot;&gt;' + l10n.dragInfo + '&lt;/div&gt;' )[0],
</span><span class="cx">                                         priority: -40
</span><span class="lines">@@ -3290,7 +3532,9 @@
</span><span class="cx">                         this.removeContent();
</span><span class="cx"> 
</span><span class="cx">                         this.uploader = new media.view.UploaderInline({
</span><del>-                                controller: this.controller
</del><ins>+                                controller: this.controller,
+                                status:     false,
+                                message:    l10n.noItemsFound
</ins><span class="cx">                         });
</span><span class="cx"> 
</span><span class="cx">                         this.views.add( this.uploader );
</span><span class="lines">@@ -3322,7 +3566,7 @@
</span><span class="cx"> 
</span><span class="cx">                         this.views.add( sidebar );
</span><span class="cx"> 
</span><del>-                        if ( options.uploads &amp;&amp; this.controller.uploader ) {
</del><ins>+                        if ( this.controller.uploader ) {
</ins><span class="cx">                                 sidebar.set( 'uploads', new media.view.UploaderStatus({
</span><span class="cx">                                         controller: this.controller,
</span><span class="cx">                                         priority:   40
</span><span class="lines">@@ -3373,57 +3617,6 @@
</span><span class="cx">         });
</span><span class="cx"> 
</span><span class="cx">         /**
</span><del>-         * wp.media.view.SelectionPreview
-         */
-        media.view.SelectionPreview = media.View.extend({
-                tagName:   'div',
-                className: 'selection-preview',
-                template:  media.template('media-selection-preview'),
-
-                events: {
-                        'click .clear-selection': 'clear'
-                },
-
-                initialize: function() {
-                        _.defaults( this.options, {
-                                clearable: true
-                        });
-
-                        this.controller = this.options.controller;
-                        this.collection.on( 'add change:url remove', this.render, this );
-                        this.render();
-                },
-
-                render: function() {
-                        var options = _.clone( this.options ),
-                                last, sizes, amount;
-
-                        // If nothing is selected, display nothing.
-                        if ( ! this.collection.length ) {
-                                this.$el.empty();
-                                return this;
-                        }
-
-                        options.count = this.collection.length;
-                        last  = this.collection.last();
-                        sizes = last.get('sizes');
-
-                        if ( 'image' === last.get('type') )
-                                options.thumbnail = ( sizes &amp;&amp; sizes.thumbnail ) ? sizes.thumbnail.url : last.get('url');
-                        else
-                                options.thumbnail =  last.get('icon');
-
-                        this.$el.html( this.template( options ) );
-                        return this;
-                },
-
-                clear: function( event ) {
-                        event.preventDefault();
-                        this.collection.reset();
-                }
-        });
-
-        /**
</del><span class="cx">          * wp.media.view.Selection
</span><span class="cx">          */
</span><span class="cx">         media.view.Selection = media.View.extend({
</span><span class="lines">@@ -3442,7 +3635,6 @@
</span><span class="cx">                                 clearable: true
</span><span class="cx">                         });
</span><span class="cx"> 
</span><del>-                        this.controller = this.options.controller;
</del><span class="cx">                         this.attachments = new media.view.Attachments({
</span><span class="cx">                                 controller: this.controller,
</span><span class="cx">                                 collection: this.collection,
</span><span class="lines">@@ -3659,22 +3851,24 @@
</span><span class="cx">                                 $input = this.$('.link-to-custom'),
</span><span class="cx">                                 attachment = this.options.attachment;
</span><span class="cx"> 
</span><del>-                        if ( 'none' === linkTo ) {
</del><ins>+                        if ( 'none' === linkTo || ( ! attachment &amp;&amp; 'custom' !== linkTo ) ) {
</ins><span class="cx">                                 $input.hide();
</span><span class="cx">                                 return;
</span><span class="cx">                         }
</span><span class="cx"> 
</span><del>-                        $input.show();
</del><ins>+                        if ( attachment ) {
+                                if ( 'post' === linkTo ) {
+                                        $input.val( attachment.get('link') );
+                                } else if ( 'file' === linkTo ) {
+                                        $input.val( attachment.get('url') );
+                                } else if ( ! this.model.get('linkUrl') ) {
+                                        $input.val('http://');
+                                }
</ins><span class="cx"> 
</span><del>-                        if ( 'post' === linkTo ) {
-                                $input.val( attachment.get('link') );
-                        } else if ( 'file' === linkTo ) {
-                                $input.val( attachment.get('url') );
-                        } else if ( ! this.model.get('linkUrl') ) {
-                                $input.val('http://');
</del><ins>+                                $input.prop( 'readonly', 'custom' !== linkTo );
</ins><span class="cx">                         }
</span><span class="cx"> 
</span><del>-                        $input.prop( 'readonly', 'custom' !== linkTo );
</del><ins>+                        $input.show();
</ins><span class="cx"> 
</span><span class="cx">                         // If the input is visible, focus and select its contents.
</span><span class="cx">                         if ( $input.is(':visible') )
</span><span class="lines">@@ -3768,12 +3962,10 @@
</span><span class="cx">         media.view.Iframe = media.View.extend({
</span><span class="cx">                 className: 'media-iframe',
</span><span class="cx"> 
</span><del>-                initialize: function() {
-                        this.controller = this.options.controller;
-                },
-
</del><span class="cx">                 render: function() {
</span><ins>+                        this.views.detach();
</ins><span class="cx">                         this.$el.html( '&lt;iframe src=&quot;' + this.controller.state().get('src') + '&quot; /&gt;' );
</span><ins>+                        this.views.render();
</ins><span class="cx">                         return this;
</span><span class="cx">                 }
</span><span class="cx">         });
</span><span class="lines">@@ -3785,11 +3977,9 @@
</span><span class="cx">                 className: 'media-embed',
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><del>-                        this.controller = this.options.controller;
-
</del><span class="cx">                         this.url = new media.view.EmbedUrl({
</span><span class="cx">                                 controller: this.controller,
</span><del>-                                model:      this.model
</del><ins>+                                model:      this.model.props
</ins><span class="cx">                         }).render();
</span><span class="cx"> 
</span><span class="cx">                         this._settings = new media.View();
</span><span class="lines">@@ -3826,7 +4016,7 @@
</span><span class="cx"> 
</span><span class="cx">                         this.settings( new constructor({
</span><span class="cx">                                 controller: this.controller,
</span><del>-                                model:      this.model,
</del><ins>+                                model:      this.model.props,
</ins><span class="cx">                                 priority:   40
</span><span class="cx">                         }) );
</span><span class="cx">                 }
</span><span class="lines">@@ -3846,15 +4036,13 @@
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><del>-                        this.label = this.make( 'span', null, this.options.label || l10n.url );
</del><span class="cx">                         this.input = this.make( 'input', {
</span><span class="cx">                                 type:  'text',
</span><span class="cx">                                 value: this.model.get('url') || ''
</span><span class="cx">                         });
</span><span class="cx"> 
</span><del>-                        this.$label = $( this.label );
</del><span class="cx">                         this.$input = $( this.input );
</span><del>-                        this.$el.append([ this.label, this.input ]);
</del><ins>+                        this.$el.append( this.input );
</ins><span class="cx"> 
</span><span class="cx">                         this.model.on( 'change:url', this.render, this );
</span><span class="cx">                 },
</span></span></pre></div>
<a id="trunkwpincludesmediaphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/media.php (23005 => 23006)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/media.php        2012-12-04 00:51:02 UTC (rev 23005)
+++ trunk/wp-includes/media.php        2012-12-04 01:26:03 UTC (rev 23006)
</span><span class="lines">@@ -1467,9 +1467,11 @@
</span><span class="cx"> 
</span><span class="cx">                 // Library
</span><span class="cx">                 'mediaLibraryTitle'  =&gt; __( 'Media Library' ),
</span><ins>+                'insertMediaTitle'   =&gt; __( 'Insert Media' ),
</ins><span class="cx">                 'createNewGallery'   =&gt; __( 'Create a new gallery' ),
</span><span class="cx">                 'returnToLibrary'    =&gt; __( '&amp;#8592; Return to library' ),
</span><span class="cx">                 'allMediaItems'      =&gt; __( 'All media items' ),
</span><ins>+                'noItemsFound'       =&gt; __( 'No items found.' ),
</ins><span class="cx">                 'insertIntoPost'     =&gt; $hier ? __( 'Insert into page' ) : __( 'Insert into post' ),
</span><span class="cx">                 'uploadedToThisPost' =&gt; $hier ? __( 'Uploaded to this page' ) : __( 'Uploaded to this post' ),
</span><span class="cx">                 'warnDelete' =&gt;      __( &quot;You are about to permanently delete this item.\n  'Cancel' to stop, 'OK' to delete.&quot; ),
</span><span class="lines">@@ -1489,6 +1491,7 @@
</span><span class="cx">                 'updateGallery'      =&gt; __( 'Update gallery' ),
</span><span class="cx">                 'continueEditing'    =&gt; __( 'Continue editing' ),
</span><span class="cx">                 'addToGallery'       =&gt; __( 'Add to gallery' ),
</span><ins>+                'addToGalleryTitle'  =&gt; __( 'Add to Gallery' ),
</ins><span class="cx">                 'reverseOrder'       =&gt; __( 'Reverse order' ),
</span><span class="cx">         );
</span><span class="cx"> 
</span><span class="lines">@@ -1517,6 +1520,8 @@
</span><span class="cx">         ?&gt;
</span><span class="cx">         &lt;script type=&quot;text/html&quot; id=&quot;tmpl-media-frame&quot;&gt;
</span><span class="cx">                 &lt;div class=&quot;media-frame-menu&quot;&gt;&lt;/div&gt;
</span><ins>+                &lt;div class=&quot;media-frame-title&quot;&gt;&lt;/div&gt;
+                &lt;div class=&quot;media-frame-router&quot;&gt;&lt;/div&gt;
</ins><span class="cx">                 &lt;div class=&quot;media-frame-content&quot;&gt;&lt;/div&gt;
</span><span class="cx">                 &lt;div class=&quot;media-frame-toolbar&quot;&gt;&lt;/div&gt;
</span><span class="cx">                 &lt;div class=&quot;media-frame-uploader&quot;&gt;&lt;/div&gt;
</span><span class="lines">@@ -1524,13 +1529,10 @@
</span><span class="cx"> 
</span><span class="cx">         &lt;script type=&quot;text/html&quot; id=&quot;tmpl-media-modal&quot;&gt;
</span><span class="cx">                 &lt;div class=&quot;media-modal wp-core-ui&quot;&gt;
</span><del>-                        &lt;h3 class=&quot;media-modal-title&quot;&gt;{{ data.title }}&lt;/h3&gt;
-                        &lt;a class=&quot;media-modal-close media-modal-icon&quot; href=&quot;#&quot; title=&quot;&lt;?php esc_attr_e('Close'); ?&gt;&quot;&gt;&lt;/a&gt;
</del><ins>+                        &lt;a class=&quot;media-modal-close&quot; href=&quot;#&quot; title=&quot;&lt;?php esc_attr_e('Close'); ?&gt;&quot;&gt;&lt;span class=&quot;media-modal-icon&quot;&gt;&lt;/span&gt;&lt;/a&gt;
</ins><span class="cx">                         &lt;div class=&quot;media-modal-content&quot;&gt;&lt;/div&gt;
</span><span class="cx">                 &lt;/div&gt;
</span><del>-                &lt;div class=&quot;media-modal-backdrop&quot;&gt;
-                        &lt;div&gt;&lt;/div&gt;
-                &lt;/div&gt;
</del><ins>+                &lt;div class=&quot;media-modal-backdrop&quot;&gt;&lt;/div&gt;
</ins><span class="cx">         &lt;/script&gt;
</span><span class="cx"> 
</span><span class="cx">         &lt;script type=&quot;text/html&quot; id=&quot;tmpl-uploader-window&quot;&gt;
</span><span class="lines">@@ -1540,16 +1542,20 @@
</span><span class="cx">         &lt;/script&gt;
</span><span class="cx"> 
</span><span class="cx">         &lt;script type=&quot;text/html&quot; id=&quot;tmpl-uploader-inline&quot;&gt;
</span><del>-                &lt;div class=&quot;uploader-inline-content&quot;&gt;
</del><ins>+                &lt;# var messageClass = data.message ? 'has-upload-message' : 'no-upload-message'; #&gt;
+                &lt;div class=&quot;uploader-inline-content {{ messageClass }}&quot;&gt;
+                &lt;# if ( data.message ) { #&gt;
+                        &lt;h3 class=&quot;upload-message&quot;&gt;{{ data.message }}&lt;/h3&gt;
+                &lt;# } #&gt;
</ins><span class="cx">                 &lt;?php if ( ! _device_can_upload() ) : ?&gt;
</span><del>-                        &lt;h3&gt;&lt;?php _e('The web browser on your device cannot be used to upload files. You may be able to use the &lt;a href=&quot;http://wordpress.org/extend/mobile/&quot;&gt;native app for your device&lt;/a&gt; instead.'); ?&gt;&lt;/h3&gt;
</del><ins>+                        &lt;h3 class=&quot;upload-instructions&quot;&gt;&lt;?php _e('The web browser on your device cannot be used to upload files. You may be able to use the &lt;a href=&quot;http://wordpress.org/extend/mobile/&quot;&gt;native app for your device&lt;/a&gt; instead.'); ?&gt;&lt;/h3&gt;
</ins><span class="cx">                 &lt;?php elseif ( is_multisite() &amp;&amp; ! is_upload_space_available() ) : ?&gt;
</span><del>-                        &lt;h3&gt;&lt;?php _e( 'Upload Limit Exceeded' ); ?&gt;&lt;/h3&gt;
</del><ins>+                        &lt;h3 class=&quot;upload-instructions&quot;&gt;&lt;?php _e( 'Upload Limit Exceeded' ); ?&gt;&lt;/h3&gt;
</ins><span class="cx">                         &lt;?php do_action( 'upload_ui_over_quota' ); ?&gt;
</span><span class="cx"> 
</span><span class="cx">                 &lt;?php else : ?&gt;
</span><span class="cx">                         &lt;div class=&quot;upload-ui&quot;&gt;
</span><del>-                                &lt;h3 class=&quot;drop-instructions&quot;&gt;&lt;?php _e( 'Drop files anywhere to upload' ); ?&gt;&lt;/h3&gt;
</del><ins>+                                &lt;h3 class=&quot;upload-instructions drop-instructions&quot;&gt;&lt;?php _e( 'Drop files anywhere to upload' ); ?&gt;&lt;/h3&gt;
</ins><span class="cx">                                 &lt;a href=&quot;#&quot; class=&quot;browser button button-hero&quot;&gt;&lt;?php _e( 'Select Files' ); ?&gt;&lt;/a&gt;
</span><span class="cx">                         &lt;/div&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -1744,19 +1750,6 @@
</span><span class="cx">                 &lt;div class=&quot;selection-view&quot;&gt;&lt;/div&gt;
</span><span class="cx">         &lt;/script&gt;
</span><span class="cx"> 
</span><del>-        &lt;script type=&quot;text/html&quot; id=&quot;tmpl-media-selection-preview&quot;&gt;
-                &lt;div class=&quot;selected-img selected-count-{{ data.count }}&quot;&gt;
-                        &lt;# if ( data.thumbnail ) { #&gt;
-                                &lt;img src=&quot;{{ data.thumbnail }}&quot; draggable=&quot;false&quot; /&gt;
-                        &lt;# } #&gt;
-
-                        &lt;span class=&quot;count&quot;&gt;{{ data.count }}&lt;/span&gt;
-                &lt;/div&gt;
-                &lt;# if ( data.clearable ) { #&gt;
-                        &lt;a class=&quot;clear-selection&quot; href=&quot;#&quot;&gt;&lt;?php _e('Clear selection'); ?&gt;&lt;/a&gt;
-                &lt;# } #&gt;
-        &lt;/script&gt;
-
</del><span class="cx">         &lt;script type=&quot;text/html&quot; id=&quot;tmpl-attachment-display-settings&quot;&gt;
</span><span class="cx">                 &lt;h3&gt;&lt;?php _e('Attachment Display Settings'); ?&gt;&lt;/h3&gt;
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>