<!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>[22362] trunk/wp-includes: Streamlining media, part I.</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/22362">22362</a></dd>
<dt>Author</dt> <dd>koopersmith</dd>
<dt>Date</dt> <dd>2012-11-04 22:59:12 +0000 (Sun, 04 Nov 2012)</dd>
</dl>

<h3>Log Message</h3>
<pre>Streamlining media, part I.

The main goal here is to rearrange the media components in a modularized structure to support more linear workflows. This is that structure using the pre-existing workflows, which will be improved over the course of the next few commits.

This leaves a few pieces a bit rough around the edges: namely gallery editing and selecting a featured image.

The fine print follows.

----

'''Styles'''
* Tightened padding around the modal to optimize for a smaller default screen size.
* Added a light dashed line surrounding the modal to provide a subtle cue for the persistent dropzone (which is evolving into a power user feature since we now have a dedicated `upload` state).
* Add a size for `hero` buttons.
* Remove transitions from frame subviews (e.g. menu, content, sidebar, toolbar).

----

'''Code'''

`wp.media.controller.StateManager`
* Don't fire `activate` and `deactivate` if attempting to switch to the current state.

`wp.media.controller.State`
* Add a base state class to bind default methods (as not all states will inherit from the `Library` state).
* On `activate`, fire `activate()`, `menu()`, `content()`, `sidebar()`, and `toolbar()`.
* The menu view is often a shared object (as its most common use case is switching between states). Assign the view to the state's `menu` attribute.
* `menu()` automatically fetches the state's `menu` attribute, attaches the menu view to the frame, and attempts to select a menu item that matches the state's `id`.

`wp.media.controller.Library`
* Now inherits from `wp.media.controller.State`.

`wp.media.controller.Upload`
* A new state to improve the upload experience.
* Displays a large dropzone when empty (a `UploaderInline` view).
* When attachments are uploaded, displays management interface (a `library` state restricted to attachments uploaded during the current session).

`wp.media.view.Frame`
* In `menu()`, `content()`, `sidebar()`, and `toolbar()`, only change the view if it differs from the current view. Also, ensure `hide-*` classes are properly removed.
*

`wp.media.view.PriorityList`
* A new container view used to sort and render child views by the `priority` property.
* Used by `wp.media.view.Sidebar` and `wp.media.view.Menu`.
* Next step: Use two instances to power `wp.media.view.Toolbar`.

`wp.media.view.Menu` and `wp.media.view.MenuItem`
* A new `PriorityList` view that renders a list of views used to switch between states.
* `MenuItem` instances have `id` attributes that are tied directly to states.
* Separators can be added as plain `Backbone.View` instances with the `separator` class.
* Supports any type of `Backbone.View`.

`media.view.Menu.Landing`
* The landing menu for the 'insert media' workflow.
* Includes an inactive link to an &quot;Embed from URL&quot; state.
* Next steps: only use in select cases to allot for other workflows (such as featured images).

`wp.media.view.AttachmentsBrowser`
* A container to render an `Attachments` view with accompanying UI controls (similar to what the `Attachments` view was when it contained the `$list` property).
* Currently only renders a `Search` view as a control.
* Next steps: Add optional view counts (e.g. &quot;21 images&quot;), upload buttons, and collection filter UI.

`wp.media.view.Attachments`
* If the `Attachments` scroll buffer is not filled with `Attachment` views, continue loading more attachments.
* Use `this.model` instead of `this.controller.state()` to allow `Attachments` views to have differing `edge` and `gutter` properties.
* Add `edge()`, a method used to calculate the optimal dimensions for an attachment based on the current width of the `Attachments` container element.
* `edge()` is currently only enabled on resize, as the relative positioning and CSS transforms used to center thumbnails are suboptimal when coupled with frequent resizing.
* Next steps: For infinite scroll performance improvements, look into absolutely positioning attachment views and paging groups of attachment views.

`wp.media.view.UploaderWindow`
* Now generates a `$browser` element as the browse button (instead of a full `UploaderInline` view). Using a portable browse button prevents us from having to create a new `wp.Uploader` instance every time we want access to a browse button.

`wp.media.view.UploaderInline`
* No longer directly linked to the `UploaderWindow` view or its `wp.Uploader` instance.
* Used as the default `upload` state view.

`wp.media.view.Selection`
* An interactive representation of the selected `Attachments`.
* Based on the improved workflows, this is likely overkill. For simplicity's sake, will probably remove this in favor of `SelectionPreview`.

----

see <a href="http://core.trac.wordpress.org/ticket/21390">#21390</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpincludescssbuttonscss">trunk/wp-includes/css/buttons.css</a></li>
<li><a href="#trunkwpincludescssmediaviewscss">trunk/wp-includes/css/media-views.css</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>
<li><a href="#trunkwpincludesscriptloaderphp">trunk/wp-includes/script-loader.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpincludescssbuttonscss"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/css/buttons.css (22361 => 22362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/css/buttons.css        2012-11-03 22:51:38 UTC (rev 22361)
+++ trunk/wp-includes/css/buttons.css        2012-11-04 22:59:12 UTC (rev 22362)
</span><span class="lines">@@ -81,6 +81,14 @@
</span><span class="cx">         padding: 0 8px 1px;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.button.button-hero,
+.button-group.button-hero .button {
+        font-size: 14px;
+        height: 46px;
+        line-height: 44px;
+        padding: 0 36px;
+}
+
</ins><span class="cx"> .button:active {
</span><span class="cx">         outline: none;
</span><span class="cx"> }
</span><span class="lines">@@ -294,7 +302,7 @@
</span><span class="cx">         position: absolute;
</span><span class="cx">         top: 100%;
</span><span class="cx">         left: 0;
</span><del>-        margin-top: 5px;
</del><ins>+        margin: 5px 0;
</ins><span class="cx">         padding: 0.8em 1em;
</span><span class="cx">         border-radius: 3px;
</span><span class="cx"> 
</span><span class="lines">@@ -314,3 +322,8 @@
</span><span class="cx">         left: auto;
</span><span class="cx">         right: 0;
</span><span class="cx"> }
</span><ins>+
+.dropdown-flip-y .dropdown {
+        top: auto;
+        bottom: 100%;
+}
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpincludescssmediaviewscss"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/css/media-views.css (22361 => 22362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/css/media-views.css        2012-11-03 22:51:38 UTC (rev 22361)
+++ trunk/wp-includes/css/media-views.css        2012-11-04 22:59:12 UTC (rev 22362)
</span><span class="lines">@@ -3,10 +3,10 @@
</span><span class="cx">  */
</span><span class="cx"> .media-modal {
</span><span class="cx">         position: fixed;
</span><del>-        top: 80px;
-        left: 60px;
-        right: 60px;
-        bottom: 60px;
</del><ins>+        top: 60px;
+        left: 40px;
+        right: 40px;
+        bottom: 40px;
</ins><span class="cx">         z-index: 125000;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -21,6 +21,15 @@
</span><span class="cx">         z-index: 120000;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.media-modal-backdrop div {
+        position: absolute;
+        top: 10px;
+        left: 10px;
+        right: 10px;
+        bottom: 10px;
+        border: 1px dashed rgba( 255, 255, 255, 0.5 );
+}
+
</ins><span class="cx"> .media-modal-title,
</span><span class="cx"> .media-modal-close {
</span><span class="cx">         position: absolute;
</span><span class="lines">@@ -38,7 +47,7 @@
</span><span class="cx">         float: left;
</span><span class="cx">         padding: 0;
</span><span class="cx">         margin: 0;
</span><del>-        font-size: 1.4em;
</del><ins>+        font-size: 16px;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> .media-modal-close {
</span><span class="lines">@@ -74,14 +83,25 @@
</span><span class="cx"> .media-toolbar {
</span><span class="cx">         position: absolute;
</span><span class="cx">         top: 0;
</span><del>-        left: 220px;
</del><ins>+        left: 0;
</ins><span class="cx">         right: 0;
</span><span class="cx">         z-index: 100;
</span><del>-        height: 50px;
-        padding: 0 10px;
-        border-bottom: 1px solid #dfdfdf;
</del><ins>+        height: 60px;
+        padding: 0 16px;
+        border: 0 solid #dfdfdf;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.media-frame &gt; .media-toolbar {
+        top: auto;
+        left: 200px;
+        bottom: 0;
+        border-width: 1px 0 0 0;
+}
+
+.media-frame.hide-toolbar &gt; .media-toolbar {
+        bottom: -61px;
+}
+
</ins><span class="cx"> .media-toolbar-primary {
</span><span class="cx">         float: right;
</span><span class="cx"> }
</span><span class="lines">@@ -94,14 +114,14 @@
</span><span class="cx"> .media-toolbar-primary &gt; .media-button-group {
</span><span class="cx">         margin-left: 10px;
</span><span class="cx">         float: left;
</span><del>-        margin-top: 10px;
</del><ins>+        margin-top: 15px;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> .media-toolbar-secondary &gt; .media-button,
</span><span class="cx"> .media-toolbar-secondary &gt; .media-button-group {
</span><span class="cx">         margin-right: 10px;
</span><span class="cx">         float: left;
</span><del>-        margin-top: 10px;
</del><ins>+        margin-top: 15px;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><span class="lines">@@ -110,18 +130,23 @@
</span><span class="cx"> .media-sidebar {
</span><span class="cx">         position: absolute;
</span><span class="cx">         top: 0;
</span><del>-        left: 0;
-        bottom: 0;
-        width: 219px;
-        z-index: 50;
</del><ins>+        right: 0;
+        bottom: 61px;
+        width: 247px;
+        padding: 0 16px;
+        z-index: 75;
</ins><span class="cx">         background: #f5f5f5;
</span><del>-        border-right: 1px solid #dfdfdf;
</del><ins>+        border-left: 1px solid #dfdfdf;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> .hide-sidebar .media-sidebar {
</span><del>-        display: none;
</del><ins>+        right: -280px;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.hide-toolbar .media-sidebar {
+        bottom: 0;
+}
+
</ins><span class="cx"> .media-sidebar .sidebar-title {
</span><span class="cx">         font-weight: 200;
</span><span class="cx">         font-size: 20px;
</span><span class="lines">@@ -147,31 +172,65 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * Frame
</del><ins>+ * Menu
</ins><span class="cx">  */
</span><ins>+.media-menu {
+        position: absolute;
+        top: 0;
+        left: 0;
+        bottom: 0;
+        width: 199px;
+        margin: 0;
+        padding: 16px 0;
+        z-index: 200;
+        box-shadow: inset -6px 0 6px -6px rgba( 0, 0, 0, 0.4 );
+}
</ins><span class="cx"> 
</span><del>-.media-frame .media-content,
-.media-frame .media-toolbar,
-.media-frame .media-sidebar {
-        -webkit-transition-property: left, right, top, bottom, margin;
-        -moz-transition-property:    left, right, top, bottom, margin;
-        -ms-transition-property:     left, right, top, bottom, margin;
-        -o-transition-property:      left, right, top, bottom, margin;
-        transition-property:         left, right, top, bottom, margin;
</del><ins>+.media-menu li {
+        position: relative;
+        padding: 4px 20px;
+        margin: 0;
+        line-height: 18px;
+        font-size: 14px;
+        color: #21759B;
+        text-shadow: 0 1px 0 #fff;
+}
</ins><span class="cx"> 
</span><del>-        -webkit-transition-duration: 0.2s;
-        -moz-transition-duration:    0.2s;
-        -ms-transition-duration:     0.2s;
-        -o-transition-duration:      0.2s;
-        transition-duration:         0.2s;
</del><ins>+.media-menu-item {
+        cursor: pointer;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.media-menu li:hover {
+        background: rgba( 0, 0, 0, 0.04 );
+}
+
+.media-menu .active,
+.media-menu .active:hover {
+        color: #333;
+        font-weight: bold;
+}
+
+.media-menu .separator {
+        height: 0;
+        margin: 12px 20px;
+        padding: 0;
+        border-top: 1px solid #dfdfdf;
+        border-bottom: 1px solid #fff;
+}
+
+/**
+ * Frame
+ */
+.media-frame {
+        overflow: hidden;
+}
+
</ins><span class="cx"> .media-frame .media-content {
</span><span class="cx">         position: absolute;
</span><del>-        top: 51px;
-        left: 220px;
-        right: 0;
-        bottom: 0;
</del><ins>+        top: 0;
+        left: 200px;
+        right: 280px;
+        bottom: 61px;
</ins><span class="cx">         height: auto;
</span><span class="cx">         width: auto;
</span><span class="cx">         margin: 0;
</span><span class="lines">@@ -179,9 +238,13 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> .media-frame.hide-sidebar .media-content {
</span><del>-        left: 0;
</del><ins>+        right: 0;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.media-frame.hide-toolbar .media-content {
+        bottom: 0;
+}
+
</ins><span class="cx"> .media-frame .media-toolbar .add-to-gallery {
</span><span class="cx">         display: none;
</span><span class="cx"> }
</span><span class="lines">@@ -199,6 +262,14 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Attachments
+ */
+.attachments {
+        margin: 0;
+        padding-right: 16px;
+}
+
+/**
</ins><span class="cx">  * Attachment
</span><span class="cx">  */
</span><span class="cx"> .attachment {
</span><span class="lines">@@ -388,7 +459,29 @@
</span><span class="cx">         border-radius: 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> /**
</span><ins>+ * Attachments Browser
+ */
+.media-frame .attachments-browser {
+        overflow: hidden;
+}
+
+.attachments-browser .media-toolbar {
+        height: 50px;
+}
+
+.attachments-browser .attachments {
+        position: absolute;
+        top: 50px;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        overflow: auto;
+}
+
+
+/**
</ins><span class="cx">  * Progress Bar
</span><span class="cx">  */
</span><span class="cx"> .media-progress-bar {
</span><span class="lines">@@ -445,10 +538,10 @@
</span><span class="cx"> 
</span><span class="cx"> .uploader-window-content {
</span><span class="cx">         position: absolute;
</span><del>-        top: 30px;
-        left: 30px;
-        right: 30px;
-        bottom: 30px;
</del><ins>+        top: 10px;
+        left: 10px;
+        right: 10px;
+        bottom: 10px;
</ins><span class="cx">         border: 1px dashed #fff;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -463,7 +556,7 @@
</span><span class="cx">         -o-transform:      translateY( -50% );
</span><span class="cx">         transform:         translateY( -50% );
</span><span class="cx"> 
</span><del>-        font-size: 18px;
</del><ins>+        font-size: 20px;
</ins><span class="cx">         font-weight: 200;
</span><span class="cx">         color: #fff;
</span><span class="cx">         padding: 0;
</span><span class="lines">@@ -485,10 +578,26 @@
</span><span class="cx">         display: block;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.uploader-inline {
-        display: none;
</del><ins>+.media-content.uploader-inline {
+        margin: 20px;
+        padding: 20px;
+        border: 1px dashed #aaa;
+        text-align: center;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.uploader-inline-content {
+        position: absolute;
+        top: 30%;
+        left: 0;
+        right: 0;
+}
+
+.uploader-inline h3 {
+        font-size: 20px;
+        font-weight: 200;
+        margin-bottom: 1.6em;
+}
+
</ins><span class="cx"> .uploader-inline .media-progress-bar {
</span><span class="cx">         display: none;
</span><span class="cx"> }
</span><span class="lines">@@ -497,23 +606,85 @@
</span><span class="cx">         display: block;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.media-sidebar .uploader-inline {
</del><ins>+.uploader-inline .browser {
+        display: inline-block !important;
+}
+
+/**
+ * Selection
+ */
+
+.media-selection {
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 350px;
+        height: 60px;
+        padding: 0 0 0 16px;
+        overflow: hidden;
+        white-space: nowrap;
+}
+
+.media-selection .selection-info {
+        display: inline-block;
+        height: 60px;
+        margin-right: 10px;
+        vertical-align: top;
+}
+
+.media-selection.empty {
+        display: none;
+}
+
+.media-selection .count {
</ins><span class="cx">         display: block;
</span><ins>+        padding-top: 12px;
+        font-size: 14px;
+        line-height: 20px;
+        font-weight: bold;
+}
+
+.media-selection .clear-selection {
+        display: block;
+        text-decoration: none;
+        line-height: 16px;
+}
+
+.media-selection .attachments {
+        display: inline-block;
+        height: 60px;
+        margin-top: 5px;
+        overflow: hidden;
+        vertical-align: top;
+}
+
+.media-selection .selected.attachment {
+        box-shadow: none;
+}
+
+.media-selection .details.attachment {
+        box-shadow:
+                0 0 0 1px #fff,
+                0 0 0 3px #1e8cbe;
+}
+
+.media-selection:after {
+        content: '';
+        display: block;
</ins><span class="cx">         position: absolute;
</span><del>-        left: 0;
</del><ins>+        top: 0;
</ins><span class="cx">         right: 0;
</span><span class="cx">         bottom: 0;
</span><del>-        height: 100px;
-        margin: 10px;
-        padding-top: 10px;
-        text-align: center;
-        border: 1px dashed #aaa;
</del><ins>+        width: 25px;
+        background-image: -webkit-gradient(linear, right top, right top, from( rgba( 255, 255, 255, 1 ) ), to( rgba( 255, 255, 255, 0 ) ));
+        background-image: -webkit-linear-gradient(right, rgba( 255, 255, 255, 1 ) ,  rgba( 255, 255, 255, 0 ) );
+        background-image:    -moz-linear-gradient(right, rgba( 255, 255, 255, 1 ) ,  rgba( 255, 255, 255, 0 ) );
+        background-image:      -o-linear-gradient(right, rgba( 255, 255, 255, 1 ) ,  rgba( 255, 255, 255, 0 ) );
+        background-image:   linear-gradient(to left, rgba( 255, 255, 255, 1 ) ,  rgba( 255, 255, 255, 0 ) );
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-.media-sidebar .uploader-inline h3 {
-        font-weight: 200;
-        font-size: 16px;
-        margin: 10px 0;
</del><ins>+.media-selection .attachment .filename {
+        display: none;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><span class="lines">@@ -584,10 +755,6 @@
</span><span class="cx">  * Attachment Details
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-.attachment-details {
-        padding-top: 20px;
-}
-
</del><span class="cx"> .attachment-details-preview {
</span><span class="cx">         cursor: default;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkwpincludesjsmediaviewsjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/js/media-views.js (22361 => 22362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/js/media-views.js        2012-11-03 22:51:38 UTC (rev 22361)
+++ trunk/wp-includes/js/media-views.js        2012-11-04 22:59:12 UTC (rev 22362)
</span><span class="lines">@@ -83,15 +83,21 @@
</span><span class="cx">                 state: function( id ) {
</span><span class="cx">                         var previous;
</span><span class="cx"> 
</span><del>-                        if ( id ) {
-                                if ( previous = this.state() )
-                                        previous.trigger('deactivate');
-                                this._state = id;
-                                return this.state().trigger('activate');
-                        }
</del><ins>+                        if ( ! id )
+                                return this._state ? this.get( this._state ) : null;
</ins><span class="cx"> 
</span><del>-                        if ( this._state )
-                                return this.get( this._state );
</del><ins>+                        previous = this.state();
+
+                        // Bail if we're trying to select the current state, or a state
+                        // that does not exist.
+                        if ( previous &amp;&amp; id === previous.id || ! this.states.get( id ) )
+                                return;
+
+                        if ( previous )
+                                previous.trigger('deactivate');
+
+                        this._state = id;
+                        this.state().trigger('activate');
</ins><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><span class="lines">@@ -107,9 +113,50 @@
</span><span class="cx">                 };
</span><span class="cx">         });
</span><span class="cx"> 
</span><ins>+
+        // wp.media.controller.State
+        // ---------------------------
+        media.controller.State = Backbone.Model.extend({
+                initialize: function() {
+                        this.on( 'activate', this._activate, this );
+                        this.on( 'activate', this.activate, this );
+                        this.on( 'deactivate', this._deactivate, this );
+                        this.on( 'deactivate', this.deactivate, this );
+                },
+
+                activate: function() {},
+                _activate: function() {
+                        this.active = true;
+
+                        this.menu();
+                        this.toolbar();
+                        this.sidebar();
+                        this.content();
+                },
+
+                deactivate: function() {},
+                _deactivate: function() {
+                        this.active = false;
+                },
+
+                menu: function() {
+                        var menu = this.get('menu');
+
+                        if ( ! menu )
+                                return;
+
+                        this.frame.menu( menu );
+                        menu.select( this.id );
+                },
+
+                toolbar: function() {},
+                sidebar: function() {},
+                content: function() {}
+        });
+
</ins><span class="cx">         // wp.media.controller.Library
</span><span class="cx">         // ---------------------------
</span><del>-        media.controller.Library = Backbone.Model.extend({
</del><ins>+        media.controller.Library = media.controller.State.extend({
</ins><span class="cx">                 defaults: {
</span><span class="cx">                         id:       'library',
</span><span class="cx">                         multiple: false,
</span><span class="lines">@@ -133,15 +180,10 @@
</span><span class="cx">                         if ( ! this.get('gutter') )
</span><span class="cx">                                 this.set( 'gutter', 8 );
</span><span class="cx"> 
</span><del>-                        this.on( 'activate', this.activate, this );
-                        this.on( 'deactivate', this.deactivate, this );
</del><ins>+                        media.controller.State.prototype.initialize.apply( this, arguments );
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 activate: function() {
</span><del>-                        this.toolbar();
-                        this.sidebar();
-                        this.content();
-
</del><span class="cx">                         // If we're in a workflow that supports multiple attachments,
</span><span class="cx">                         // automatically select any uploading attachments.
</span><span class="cx">                         if ( this.get('multiple') )
</span><span class="lines">@@ -153,6 +195,7 @@
</span><span class="cx"> 
</span><span class="cx">                 deactivate: function() {
</span><span class="cx">                         var toolbar = this._postLibraryToolbar;
</span><ins>+
</ins><span class="cx">                         if ( toolbar )
</span><span class="cx">                                 this.get('selection').off( 'add remove', toolbar.visibility, toolbar );
</span><span class="cx"> 
</span><span class="lines">@@ -184,30 +227,16 @@
</span><span class="cx">                         }) );
</span><span class="cx"> 
</span><span class="cx">                         this.details();
</span><del>-                        frame.sidebar().add({
-                                search: new media.view.Search({
-                                        controller: frame,
-                                        model:      this.get('library').props,
-                                        priority:   20
-                                }),
-
-                                selection: new media.view.SelectionPreview({
-                                        controller: frame,
-                                        collection: this.get('selection'),
-                                        priority:   40
-                                })
-                        });
</del><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 content: function() {
</span><span class="cx">                         var frame = this.frame;
</span><span class="cx"> 
</span><span class="cx">                         // Content.
</span><del>-                        frame.content( new media.view.Attachments({
</del><ins>+                        frame.content( new media.view.AttachmentsBrowser({
</ins><span class="cx">                                 controller: frame,
</span><span class="cx">                                 collection: this.get('library'),
</span><del>-                                // The single `Attachment` view to be used in the `Attachments` view.
-                                AttachmentView: media.view.Attachment.Library
</del><ins>+                                model:      this
</ins><span class="cx">                         }).render() );
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="lines">@@ -255,6 +284,65 @@
</span><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><ins>+
+        // wp.media.controller.Upload
+        // ---------------------------
+        media.controller.Upload = media.controller.Library.extend({
+                defaults: _.defaults({
+                        id: 'upload'
+                }, media.controller.Library.prototype.defaults ),
+
+                initialize: function() {
+                        var library = this.get('library');
+
+                        // If a `library` attribute isn't provided, create a new
+                        // `Attachments` collection that observes (and thereby receives
+                        // all uploading) attachments.
+                        if ( ! library ) {
+                                library = new Attachments();
+                                library.props.set({
+                                        orderby: 'date',
+                                        order:   'ASC'
+                                });
+                                library.observe( wp.Uploader.queue );
+                                this.set( 'library', library );
+                        }
+
+                        media.controller.Library.prototype.initialize.apply( this, arguments );
+                },
+
+                activate: function() {
+                        this.get('library').on( 'add remove reset', this.refresh, this );
+                        media.controller.Library.prototype.activate.apply( this, arguments );
+                        this.refresh();
+                },
+
+                deactivate: function() {
+                        this.get('library').off( 'add remove reset', this.refresh, this );
+                        media.controller.Library.prototype.deactivate.apply( this, arguments );
+                },
+
+                refresh: function() {
+                        this.frame.$el.toggleClass( 'hide-sidebar hide-toolbar', ! this.get('library').length );
+                        this.content();
+                },
+
+                content: function() {
+                        var frame = this.frame,
+                                upload;
+
+                        if ( this.get('library').length ) {
+                                media.controller.Library.prototype.content.apply( this, arguments );
+                        } else {
+                                upload = new media.view.UploaderInline({
+                                        controller: frame
+                                }).render();
+
+                                frame.content( upload );
+                        }
+                }
+        });
+
</ins><span class="cx">         // wp.media.controller.Gallery
</span><span class="cx">         // ---------------------------
</span><span class="cx">         media.controller.Gallery = media.controller.Library.extend({
</span><span class="lines">@@ -296,6 +384,7 @@
</span><span class="cx">                         this.frame.content( new media.view.Attachments({
</span><span class="cx">                                 controller: this.frame,
</span><span class="cx">                                 collection: this.get('library'),
</span><ins>+                                model:      this,
</ins><span class="cx">                                 sortable:   true,
</span><span class="cx">                                 // The single `Attachment` view to be used in the `Attachments` view.
</span><span class="cx">                                 AttachmentView: media.view.Attachment.Gallery
</span><span class="lines">@@ -345,7 +434,7 @@
</span><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><span class="cx">                         _.defaults( this.options, {
</span><del>-                                state:     'library',
</del><ins>+                                state:     'upload',
</ins><span class="cx">                                 title:     '',
</span><span class="cx">                                 selection: [],
</span><span class="cx">                                 library:   {},
</span><span class="lines">@@ -361,12 +450,12 @@
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 render: function() {
</span><del>-                        var els = [ this.toolbar().el, this.sidebar().el, this.content().el ];
</del><ins>+                        var els = [  this.menu().el, this.content().el, this.sidebar().el, this.toolbar().el ];
</ins><span class="cx"> 
</span><span class="cx">                         if ( this.modal )
</span><span class="cx">                                 this.modal.render();
</span><span class="cx"> 
</span><del>-                        // Detach any views that will be rebound to maintain event bidnings.
</del><ins>+                        // Detach any views that will be rebound to maintain event bindings.
</ins><span class="cx">                         this.$el.children().filter( els ).detach();
</span><span class="cx">                         this.$el.empty().append( els );
</span><span class="cx"> 
</span><span class="lines">@@ -389,7 +478,12 @@
</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,
+                                menus = {
+                                        landing: new media.view.Menu.Landing({
+                                                controller: this
+                                        })
+                                };
</ins><span class="cx"> 
</span><span class="cx">                         // Create the default `states` collection.
</span><span class="cx">                         this.states = new Backbone.Collection();
</span><span class="lines">@@ -404,8 +498,13 @@
</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:  this.options.multiple,
+                                        menu:      menus.landing
</ins><span class="cx">                                 }),
</span><ins>+                                new media.controller.Upload({
+                                        multiple: this.options.multiple,
+                                        menu:     menus.landing
+                                }),
</ins><span class="cx">                                 new media.controller.Gallery({
</span><span class="cx">                                         library: options.selection,
</span><span class="cx">                                         editing: options.editing
</span><span class="lines">@@ -419,7 +518,7 @@
</span><span class="cx"> 
</span><span class="cx">                 createSubviews: function() {
</span><span class="cx">                         // Initialize a stub view for each subview region.
</span><del>-                        _.each(['toolbar','sidebar','content'], function( subview ) {
</del><ins>+                        _.each(['menu','content','sidebar','toolbar'], function( subview ) {
</ins><span class="cx">                                 this[ '_' + subview ] = new Backbone.View({
</span><span class="cx">                                         tagName:   'div',
</span><span class="cx">                                         className: 'media-' + subview
</span><span class="lines">@@ -450,15 +549,21 @@
</span><span class="cx">         _.extend( media.view.Frame.prototype, media.controller.StateMachine.prototype );
</span><span class="cx"> 
</span><span class="cx">         // Create methods to fetch and replace individual subviews.
</span><del>-        _.each(['toolbar','sidebar','content'], function( subview ) {
</del><ins>+        _.each(['menu','content','sidebar','toolbar'], function( subview ) {
</ins><span class="cx">                 media.view.Frame.prototype[ subview ] = function( view ) {
</span><span class="cx">                         var previous = this[ '_' + subview ];
</span><span class="cx"> 
</span><span class="cx">                         if ( ! view )
</span><span class="cx">                                 return previous;
</span><span class="cx"> 
</span><ins>+                        if ( view === previous )
+                                return;
+
</ins><span class="cx">                         view.$el.addClass( 'media-' + subview );
</span><span class="cx"> 
</span><ins>+                        // Remove the hide class.
+                        this.$el.removeClass( 'hide-' + subview );
+
</ins><span class="cx">                         if ( previous.destroy )
</span><span class="cx">                                 previous.destroy();
</span><span class="cx">                         previous.undelegateEvents();
</span><span class="lines">@@ -564,17 +669,12 @@
</span><span class="cx">                         var uploader;
</span><span class="cx"> 
</span><span class="cx">                         this.controller = this.options.controller;
</span><del>-                        this.inline = new media.view.UploaderInline({
-                                controller:     this.controller,
-                                uploaderWindow: this
-                        }).render();
</del><span class="cx"> 
</span><del>-                        this.inline.$el.appendTo('body');
</del><ins>+                        this.$browser = $('&lt;a href=&quot;#&quot; class=&quot;browser&quot; /&gt;').hide().appendTo('body');
</ins><span class="cx"> 
</span><span class="cx">                         uploader = this.options.uploader = _.defaults( this.options.uploader || {}, {
</span><del>-                                container: this.inline.$el,
</del><span class="cx">                                 dropzone:  this.$el,
</span><del>-                                browser:   this.inline.$('.browser'),
</del><ins>+                                browser:   this.$browser,
</ins><span class="cx">                                 params:    {}
</span><span class="cx">                         });
</span><span class="cx"> 
</span><span class="lines">@@ -647,6 +747,9 @@
</span><span class="cx">                 initialize: function() {
</span><span class="cx">                         this.controller = this.options.controller;
</span><span class="cx"> 
</span><ins>+                        if ( ! this.options.$browser )
+                                this.options.$browser = this.controller.uploader.$browser;
+
</ins><span class="cx">                         // Track uploading attachments.
</span><span class="cx">                         wp.Uploader.queue.on( 'add remove reset change:percent', this.renderUploadProgress, this );
</span><span class="cx">                 },
</span><span class="lines">@@ -656,8 +759,17 @@
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 render: function() {
</span><ins>+                        var $browser = this.options.$browser,
+                                $placeholder;
+
</ins><span class="cx">                         this.renderUploadProgress();
</span><span class="cx">                         this.$el.html( this.template( this.options ) );
</span><ins>+
+                        $placeholder = this.$('.browser');
+                        $browser.text( $placeholder.text() );
+                        $browser[0].className = $placeholder[0].className;
+                        $placeholder.replaceWith( $browser.show() );
+
</ins><span class="cx">                         this.$bar = this.$('.media-progress-bar div');
</span><span class="cx">                         return this;
</span><span class="cx">                 },
</span><span class="lines">@@ -679,7 +791,6 @@
</span><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><del>-
</del><span class="cx">         /**
</span><span class="cx">          * wp.media.view.Toolbar
</span><span class="cx">          */
</span><span class="lines">@@ -765,6 +876,12 @@
</span><span class="cx">                                 controller = this.options.controller;
</span><span class="cx"> 
</span><span class="cx">                         this.options.items = {
</span><ins>+                                selection: new media.view.Selection({
+                                        controller: controller,
+                                        collection: selection,
+                                        priority:   -40
+                                }).render(),
+
</ins><span class="cx">                                 'create-new-gallery': {
</span><span class="cx">                                         style:    'primary',
</span><span class="cx">                                         text:     l10n.createNewGallery,
</span><span class="lines">@@ -777,7 +894,7 @@
</span><span class="cx"> 
</span><span class="cx">                                 'insert-into-post': new media.view.ButtonGroup({
</span><span class="cx">                                         priority: 30,
</span><del>-                                        classes:  'dropdown-flip-x',
</del><ins>+                                        classes:  'dropdown-flip-x dropdown-flip-y',
</ins><span class="cx">                                         buttons:  [
</span><span class="cx">                                                 {
</span><span class="cx">                                                         text:  l10n.insertIntoPost,
</span><span class="lines">@@ -1033,19 +1150,19 @@
</span><span class="cx">         });
</span><span class="cx"> 
</span><span class="cx">         /**
</span><del>-         * wp.media.view.Sidebar
</del><ins>+         * wp.media.view.PriorityList
</ins><span class="cx">          */
</span><del>-        media.view.Sidebar = Backbone.View.extend({
</del><ins>+
+        media.view.PriorityList = Backbone.View.extend({
</ins><span class="cx">                 tagName:   'div',
</span><del>-                className: 'media-sidebar',
-                template:  media.template('sidebar'),
</del><span class="cx"> 
</span><span class="cx">                 initialize: function() {
</span><span class="cx">                         this.controller = this.options.controller;
</span><span class="cx">                         this._views     = {};
</span><span class="cx"> 
</span><del>-                        if ( this.options.views )
-                                this.add( this.options.views, { silent: true });
</del><ins>+                        this.add( _.extend( {}, this.views, this.options.views ), { silent: true });
+                        delete this.views;
+                        delete this.options.views;
</ins><span class="cx"> 
</span><span class="cx">                         if ( ! this.options.silent )
</span><span class="cx">                                 this.render();
</span><span class="lines">@@ -1060,18 +1177,7 @@
</span><span class="cx">                         // Otherwise, `jQuery.html()` will unbind their events.
</span><span class="cx">                         $( els ).detach();
</span><span class="cx"> 
</span><del>-                        this.$el.html( this.template({
-                                title:    this.controller.state().get('title') || '',
-                                uploader: this.controller.options.uploader
-                        }) );
-
-                        this.$('.sidebar-content').html( els );
-
-                        if ( this.controller.uploader ) {
-                                this.$el.append( this.controller.uploader.inline.$el );
-                                this.controller.uploader.refresh();
-                        }
-
</del><ins>+                        this.$el.html( els );
</ins><span class="cx">                         return this;
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="lines">@@ -1089,6 +1195,9 @@
</span><span class="cx">                                 return this;
</span><span class="cx">                         }
</span><span class="cx"> 
</span><ins>+                        if ( ! (view instanceof Backbone.View) )
+                                view = this.toView( view, id, options );
+
</ins><span class="cx">                         view.controller = view.controller || this.controller;
</span><span class="cx"> 
</span><span class="cx">                         this._views[ id ] = view;
</span><span class="lines">@@ -1106,10 +1215,95 @@
</span><span class="cx">                         if ( ! options || ! options.silent )
</span><span class="cx">                                 this.render();
</span><span class="cx">                         return this;
</span><ins>+                },
+
+                toView: function( options ) {
+                        return new Backbone.View( options );
</ins><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">         /**
</span><ins>+         * wp.media.view.Menu
+         */
+        media.view.Menu = media.view.PriorityList.extend({
+                tagName:   'ul',
+                className: 'media-menu',
+
+                toView: function( options, id ) {
+                        options = options || {};
+                        options.id = id;
+                        return new media.view.MenuItem( options ).render();
+                },
+
+                select: function( id ) {
+                        var view = this.get( id );
+
+                        if ( ! view )
+                                return;
+
+                        this.deselect();
+                        view.$el.addClass('active');
+                },
+
+                deselect: function() {
+                        this.$el.children().removeClass('active');
+                }
+        });
+
+        media.view.MenuItem = Backbone.View.extend({
+                tagName:   'li',
+                className: 'media-menu-item',
+
+                events: {
+                        'click': 'toState'
+                },
+
+                toState: function() {
+                        this.controller.state( this.options.id );
+                },
+
+                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;
+                }
+        });
+
+        media.view.Menu.Landing = media.view.Menu.extend({
+                views: {
+                        upload: {
+                                text: l10n.uploadFilesTitle,
+                                priority: 20
+                        },
+                        library: {
+                                text: l10n.mediaLibraryTitle,
+                                priority: 40
+                        },
+                        separateLibrary: new Backbone.View({
+                                className: 'separator',
+                                priority: 60
+                        }),
+                        embed: {
+                                text: l10n.embedFromUrlTitle,
+                                priority: 80
+                        }
+                }
+        });
+
+        /**
+         * wp.media.view.Sidebar
+         */
+        media.view.Sidebar = media.view.PriorityList.extend({
+                className: 'media-sidebar'
+        });
+
+        /**
</ins><span class="cx">          * wp.media.view.Attachment
</span><span class="cx">          */
</span><span class="cx">         media.view.Attachment = Backbone.View.extend({
</span><span class="lines">@@ -1118,7 +1312,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>+                        'mousedown .attachment-preview': 'toggleSelection',
</ins><span class="cx">                         'change .describe':          'describe'
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="lines">@@ -1322,29 +1516,47 @@
</span><span class="cx"> 
</span><span class="cx">                         this.initSortable();
</span><span class="cx"> 
</span><del>-                        this.controller.state().on( 'change:edge change:gutter', this.css, this );
</del><ins>+                        _.bindAll( this, 'css' );
+                        this.model.on( 'change:edge change:gutter', this.css, this );
+                        this._resizeCss = _.debounce( _.bind( this.css, this ), this.refreshSensitivity );
+                        $(window).on( 'resize.attachments', this._resizeCss );
</ins><span class="cx">                         this.css();
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 destroy: function() {
</span><span class="cx">                         this.collection.off( 'add remove reset', null, this );
</span><del>-                        this.controller.state().off( 'change:edge change:gutter', this.css, this );
</del><ins>+                        this.model.off( 'change:edge change:gutter', this.css, this );
+                        $(window).off( 'resize.attachments', this._resizeCss );
</ins><span class="cx">                 },
</span><span class="cx"> 
</span><span class="cx">                 css: function() {
</span><del>-                        var $css = $( '#' + this.el.id + '-css' ),
-                                state = this.controller.state();
</del><ins>+                        var $css = $( '#' + this.el.id + '-css' );
</ins><span class="cx"> 
</span><span class="cx">                         if ( $css.length )
</span><span class="cx">                                 $css.remove();
</span><span class="cx"> 
</span><span class="cx">                         media.view.Attachments.$head().append( this.template({
</span><span class="cx">                                 id:     this.el.id,
</span><del>-                                edge:   state.get('edge'),
-                                gutter: state.get('gutter')
</del><ins>+                                edge:   this.edge(),
+                                gutter: this.model.get('gutter')
</ins><span class="cx">                         }) );
</span><span class="cx">                 },
</span><span class="cx"> 
</span><ins>+                edge: function() {
+                        var edge = this.model.get('edge'),
+                                gutter, width, columns;
+
+                        if ( ! this.$el.is(':visible') )
+                                return edge;
+
+
+                        gutter  = this.model.get('gutter') * 2;
+                        width   = this.$el.width() - gutter;
+                        columns = Math.ceil( width / ( edge + gutter ) );
+                        edge = Math.floor( ( width - ( columns * gutter ) ) / columns );
+                        return edge;
+                },
+
</ins><span class="cx">                 initSortable: function() {
</span><span class="cx">                         var collection = this.collection,
</span><span class="cx">                                 from;
</span><span class="lines">@@ -1393,7 +1605,7 @@
</span><span class="cx">                 render: function() {
</span><span class="cx">                         // If there are no elements, load some.
</span><span class="cx">                         if ( ! this.collection.length ) {
</span><del>-                                this.collection.more();
</del><ins>+                                this.collection.more().done( this.scroll );
</ins><span class="cx">                                 this.$el.empty();
</span><span class="cx">                                 return this;
</span><span class="cx">                         }
</span><span class="lines">@@ -1410,6 +1622,7 @@
</span><span class="cx">                         // Then, trigger the scroll event to check if we're within the
</span><span class="cx">                         // threshold to query for additional attachments.
</span><span class="cx">                         this.scroll();
</span><ins>+
</ins><span class="cx">                         return this;
</span><span class="cx">                 },
</span><span class="cx"> 
</span><span class="lines">@@ -1441,7 +1654,7 @@
</span><span class="cx">                                 return;
</span><span class="cx"> 
</span><span class="cx">                         if ( this.el.scrollHeight &lt; this.el.scrollTop + ( this.el.clientHeight * this.options.refreshThreshold ) ) {
</span><del>-                                this.collection.more();
</del><ins>+                                this.collection.more().done( this.scroll );
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx">         }, {
</span><span class="lines">@@ -1482,7 +1695,55 @@
</span><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx">         /**
</span><ins>+         * wp.media.view.AttachmentsBrowser
+         */
+        media.view.AttachmentsBrowser = Backbone.View.extend({
+                tagName:   'div',
+                className: 'attachments-browser',
+
+                initialize: function() {
+                        this.controller = this.options.controller;
+
+                        _.defaults( this.options, {
+                                search: true,
+                                upload: false,
+                                total:  true
+                        });
+
+                        this.toolbar = new media.view.Toolbar({
+                                controller: this.controller
+                        });
+
+                        if ( this.options.search ) {
+                                this.toolbar.add( 'search', new media.view.Search({
+                                        controller: this.controller,
+                                        model:      this.collection.props,
+                                        priority:   -40
+                                }) );
+                        }
+
+                        this.attachments = new media.view.Attachments({
+                                controller: this.controller,
+                                collection: this.collection,
+                                model:      this.model,
+                                sortable:   this.options.sortable,
+                                // The single `Attachment` view to be used in the `Attachments` view.
+                                AttachmentView: media.view.Attachment.Library
+                        });
+                },
+
+                render: function() {
+                        this.toolbar.$el.detach();
+                        this.attachments.$el.detach();
+                        this.$el.html([ this.toolbar.render().el, this.attachments.render().el ]);
+                        return this;
+                }
+        });
+
+        /**
</ins><span class="cx">          * wp.media.view.SelectionPreview
</span><span class="cx">          */
</span><span class="cx">         media.view.SelectionPreview = Backbone.View.extend({
</span><span class="lines">@@ -1533,8 +1794,85 @@
</span><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><ins>+        /**
+         * wp.media.view.Selection
+         */
+        media.view.Selection = Backbone.View.extend({
+                tagName:   'div',
+                className: 'media-selection',
+                template:  media.template('media-selection'),
</ins><span class="cx"> 
</span><ins>+                events: {
+                        'click .clear-selection': 'clear'
+                },
+
+                initialize: function() {
+                        _.defaults( this.options, {
+                                clearable: true
+                        });
+
+                        this.controller = this.options.controller;
+                        this.attachments = new media.view.Attachments({
+                                controller: this.controller,
+                                collection: this.collection,
+                                sortable:   true,
+                                model:      new Backbone.Model({
+                                        edge:   40,
+                                        gutter: 5
+                                }),
+
+                                // The single `Attachment` view to be used in the `Attachments` view.
+                                AttachmentView: media.view.Attachment.Selection
+                        });
+
+                        this.collection.on( 'add remove reset', this.refresh, this );
+                },
+
+                destroy: function() {
+                        this.collection.off( 'add remove reset', this.refresh, this );
+                },
+
+                render: function() {
+                        this.attachments.$el.detach();
+                        this.attachments.render();
+
+                        this.$el.html( this.template( this.options ) );
+
+                        this.$('.selection-view').replaceWith( this.attachments.$el );
+                        this.refresh();
+                        return this;
+                },
+
+                refresh: function() {
+                        // If the selection hasn't been rendered, bail.
+                        if ( ! this.$el.children().length )
+                                return;
+
+                        // If nothing is selected, display nothing.
+                        this.$el.toggleClass( 'empty', ! this.collection.length );
+                        this.$('.count').text( this.collection.length + ' ' + l10n.selected );
+                },
+
+                clear: function( event ) {
+                        event.preventDefault();
+                        this.collection.clear();
+                }
+        });
+
+
</ins><span class="cx">         /**
</span><ins>+         * wp.media.view.Attachment.Selection
+         */
+        media.view.Attachment.Selection = media.view.Attachment.extend({
+                // On click, just select the model, instead of removing the model from
+                // the selection.
+                toggleSelection: function() {
+                        this.controller.state().get('selection').single( this.model );
+                }
+        });
+
+
+        /**
</ins><span class="cx">          * wp.media.view.Settings
</span><span class="cx">          */
</span><span class="cx">         media.view.Settings = Backbone.View.extend({
</span></span></pre></div>
<a id="trunkwpincludesmediaphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/media.php (22361 => 22362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/media.php        2012-11-03 22:51:38 UTC (rev 22361)
+++ trunk/wp-includes/media.php        2012-11-04 22:59:12 UTC (rev 22362)
</span><span class="lines">@@ -1300,7 +1300,9 @@
</span><span class="cx">                         &lt;h3 class=&quot;media-modal-title&quot;&gt;&lt;%- title %&gt;&lt;/h3&gt;
</span><span class="cx">                         &lt;a class=&quot;media-modal-close&quot; href=&quot;&quot; title=&quot;&lt;?php esc_attr_e('Close'); ?&gt;&quot;&gt;&amp;times;&lt;/a&gt;
</span><span class="cx">                 &lt;/div&gt;
</span><del>-                &lt;div class=&quot;media-modal-backdrop&quot;&gt;&lt;/div&gt;
</del><ins>+                &lt;div class=&quot;media-modal-backdrop&quot;&gt;
+                        &lt;div&gt;&lt;/div&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">@@ -1310,17 +1312,13 @@
</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;h3&gt;&lt;?php _e( 'Drop files here' ); ?&gt;&lt;/h3&gt;
-                &lt;!--&lt;span&gt;&lt;?php _ex( 'or', 'Uploader: Drop files here - or - Select Files' ); ?&gt;&lt;/span&gt;--&gt;
-                &lt;a href=&quot;#&quot; class=&quot;browser button-secondary&quot;&gt;&lt;?php _e( 'Select Files' ); ?&gt;&lt;/a&gt;
-                &lt;div class=&quot;media-progress-bar&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;
</del><ins>+                &lt;div class=&quot;uploader-inline-content&quot;&gt;
+                        &lt;h3&gt;&lt;?php _e( 'Drop files anywhere to upload' ); ?&gt;&lt;/h3&gt;
+                        &lt;a href=&quot;#&quot; class=&quot;browser button button-hero&quot;&gt;&lt;?php _e( 'Select Files' ); ?&gt;&lt;/a&gt;
+                        &lt;div class=&quot;media-progress-bar&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;
+                &lt;/div&gt;
</ins><span class="cx">         &lt;/script&gt;
</span><span class="cx"> 
</span><del>-        &lt;script type=&quot;text/html&quot; id=&quot;tmpl-sidebar&quot;&gt;
-                &lt;h2 class=&quot;sidebar-title&quot;&gt;&lt;%- title %&gt;&lt;/h2&gt;
-                &lt;div class=&quot;sidebar-content&quot;&gt;&lt;/div&gt;
-        &lt;/script&gt;
-
</del><span class="cx">         &lt;script type=&quot;text/html&quot; id=&quot;tmpl-attachment&quot;&gt;
</span><span class="cx">                 &lt;div class=&quot;attachment-preview type-&lt;%- type %&gt; subtype-&lt;%- subtype %&gt; &lt;%- orientation %&gt;&quot;&gt;
</span><span class="cx">                         &lt;% if ( uploading ) { %&gt;
</span><span class="lines">@@ -1360,6 +1358,7 @@
</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-attachment-details&quot;&gt;
</span><ins>+                &lt;h3&gt;&lt;?php _e('Edit Attachment Details'); ?&gt;&lt;/h3&gt;
</ins><span class="cx">                 &lt;div class=&quot;attachment-preview attachment-details-preview type-&lt;%- type %&gt; subtype-&lt;%- subtype %&gt; &lt;%- orientation %&gt;&quot;&gt;
</span><span class="cx">                         &lt;% if ( uploading ) { %&gt;
</span><span class="cx">                                 &lt;div class=&quot;media-progress-bar&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;
</span><span class="lines">@@ -1392,6 +1391,16 @@
</span><span class="cx">                 &lt;% } %&gt;
</span><span class="cx">         &lt;/script&gt;
</span><span class="cx"> 
</span><ins>+        &lt;script type=&quot;text/html&quot; id=&quot;tmpl-media-selection&quot;&gt;
+                &lt;div class=&quot;selection-info&quot;&gt;
+                        &lt;span class=&quot;count&quot;&gt;&lt;/span&gt;
+                        &lt;% if ( clearable ) { %&gt;
+                                &lt;a class=&quot;clear-selection&quot; href=&quot;#&quot;&gt;&lt;?php _e('Clear'); ?&gt;&lt;/a&gt;
+                        &lt;% } %&gt;
+                &lt;/div&gt;
+                &lt;div class=&quot;selection-view&quot;&gt;&lt;/div&gt;
+        &lt;/script&gt;
+
</ins><span class="cx">         &lt;script type=&quot;text/html&quot; id=&quot;tmpl-media-selection-preview&quot;&gt;
</span><span class="cx">                 &lt;div class=&quot;selected-img selected-count-&lt;%- count %&gt;&quot;&gt;
</span><span class="cx">                         &lt;% if ( thumbnail ) { %&gt;
</span><span class="lines">@@ -1486,7 +1495,7 @@
</span><span class="cx">         &lt;script type=&quot;text/html&quot; id=&quot;tmpl-attachments-css&quot;&gt;
</span><span class="cx">                 &lt;style type=&quot;text/css&quot; id=&quot;&lt;%- id %&gt;-css&quot;&gt;
</span><span class="cx">                         #&lt;%- id %&gt; {
</span><del>-                                padding: &lt;%- gutter %&gt;px;
</del><ins>+                                padding: 0 &lt;%- gutter %&gt;px;
</ins><span class="cx">                         }
</span><span class="cx"> 
</span><span class="cx">                         #&lt;%- id %&gt; .attachment {
</span></span></pre></div>
<a id="trunkwpincludesscriptloaderphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/script-loader.php (22361 => 22362)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/script-loader.php        2012-11-03 22:51:38 UTC (rev 22361)
+++ trunk/wp-includes/script-loader.php        2012-11-04 22:59:12 UTC (rev 22362)
</span><span class="lines">@@ -327,13 +327,21 @@
</span><span class="cx">                 'search'      =&gt; __( 'Search' ),
</span><span class="cx">                 'cancel'      =&gt; __( 'Cancel' ),
</span><span class="cx">                 'addImages'   =&gt; __( 'Add images' ),
</span><ins>+                'selected'    =&gt; __( 'selected' ),
</ins><span class="cx"> 
</span><ins>+                // Upload
+                'uploadFilesTitle' =&gt; __( 'Upload Files' ),
+                'selectFiles'      =&gt; __( 'Select files' ),
+
</ins><span class="cx">                 // Library
</span><del>-                'mediaLibraryTitle'     =&gt; __( 'Media Library' ),
-                'createNewGallery'      =&gt; __( 'Create a new gallery' ),
-                'insertIntoPost'        =&gt; __( 'Insert into post' ),
-                'addToGallery'          =&gt; __( 'Add to gallery' ),
</del><ins>+                'mediaLibraryTitle' =&gt; __( 'Media Library' ),
+                'createNewGallery'  =&gt; __( 'Create a new gallery' ),
+                'insertIntoPost'    =&gt; __( 'Insert into post' ),
+                'addToGallery'      =&gt; __( 'Add to gallery' ),
</ins><span class="cx"> 
</span><ins>+                // Embed
+                'embedFromUrlTitle' =&gt; __( 'Embed From URL' ),
+
</ins><span class="cx">                 // Gallery
</span><span class="cx">                 'createGalleryTitle' =&gt; __( 'Create Gallery' ),
</span><span class="cx">                 'insertGallery'      =&gt; __( 'Insert gallery' ),
</span></span></pre>
</div>
</div>

</body>
</html>