<!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>[22547] trunk: Media: Add Embed from URL tab.</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/22547">22547</a></dd>
<dt>Author</dt> <dd>koopersmith</dd>
<dt>Date</dt> <dd>2012-11-12 05:57:12 +0000 (Mon, 12 Nov 2012)</dd>
</dl>
<h3>Log Message</h3>
<pre>Media: Add Embed from URL tab.
Note: There is a bug that currently blocks adding several successive embeds.
see <a href="http://core.trac.wordpress.org/ticket/21390">#21390</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpadminincludesmetaboxesphp">trunk/wp-admin/includes/meta-boxes.php</a></li>
<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="#trunkwpadminjsmediauploadjs">trunk/wp-admin/js/media-upload.js</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>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpadminincludesmetaboxesphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/meta-boxes.php (22546 => 22547)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/meta-boxes.php        2012-11-11 22:58:32 UTC (rev 22546)
+++ trunk/wp-admin/includes/meta-boxes.php        2012-11-12 05:57:12 UTC (rev 22547)
</span><span class="lines">@@ -1053,7 +1053,7 @@
</span><span class="cx">                         frame = wp.media( options );
</span><span class="cx">
</span><span class="cx">                         frame.toolbar.on( 'activate:select', function() {
</span><del>-                                frame.toolbar.view().add({
</del><ins>+                                frame.toolbar.view().set({
</ins><span class="cx">                                         select: {
</span><span class="cx">                                                 style: 'primary',
</span><span class="cx">                                                 text: update,
</span></span></pre></div>
<a id="trunkwpadminjscustombackgroundjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/js/custom-background.js (22546 => 22547)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/js/custom-background.js        2012-11-11 22:58:32 UTC (rev 22546)
+++ trunk/wp-admin/js/custom-background.js        2012-11-12 05:57:12 UTC (rev 22547)
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx">                         });
</span><span class="cx">
</span><span class="cx">                         frame.toolbar.on( 'activate:select', function() {
</span><del>-                                frame.toolbar.view().add({
</del><ins>+                                frame.toolbar.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 (22546 => 22547)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/js/custom-header.js        2012-11-11 22:58:32 UTC (rev 22546)
+++ trunk/wp-admin/js/custom-header.js        2012-11-12 05:57:12 UTC (rev 22547)
</span><span class="lines">@@ -25,7 +25,7 @@
</span><span class="cx">                         });
</span><span class="cx">
</span><span class="cx">                         frame.toolbar.on( 'activate:select', function() {
</span><del>-                                frame.toolbar.view().add({
</del><ins>+                                frame.toolbar.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="trunkwpadminjsmediauploadjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/js/media-upload.js (22546 => 22547)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/js/media-upload.js        2012-11-11 22:58:32 UTC (rev 22546)
+++ trunk/wp-admin/js/media-upload.js        2012-11-12 05:57:12 UTC (rev 22547)
</span><span class="lines">@@ -144,6 +144,52 @@
</span><span class="cx">                                 this.insert( shortcode.string() );
</span><span class="cx">                         }, this );
</span><span class="cx">
</span><ins>+                        workflow.get('embed').on( 'select', function() {
+                                var embed = workflow.state().toJSON(),
+                                        options;
+
+                                if ( 'link' === embed.type ) {
+                                        this.insert( wp.html.string({
+                                                tag: 'a',
+                                                content: embed.title || embed.url,
+                                                attrs: {
+                                                        href: embed.url
+                                                }
+                                        }) );
+
+                                } else if ( 'image' === embed.type ) {
+                                        _.defaults( embed, {
+                                                align: 'none',
+                                                url: '',
+                                                alt: '',
+                                                linkUrl: '',
+                                                link: 'none'
+                                        });
+
+                                        options = {
+                                                single: true,
+                                                tag: 'img',
+                                                attrs: {
+                                                        'class': 'align' + embed.align,
+                                                        src: embed.url,
+                                                        alt: embed.alt
+                                                }
+                                        };
+
+                                        if ( 'custom' === embed.link || 'file' === embed.link ) {
+                                                options = {
+                                                        tag: 'a',
+                                                        content: options,
+                                                        attrs: {
+                                                                href: 'custom' === embed.link ? embed.linkUrl : embed.url
+                                                        }
+                                                };
+                                        }
+
+                                        this.insert( wp.html.string( options ) );
+                                }
+                        }, this );
+
</ins><span class="cx">                         return workflow;
</span><span class="cx">                 },
</span><span class="cx">
</span></span></pre></div>
<a id="trunkwpincludescssmediaviewscss"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/css/media-views.css (22546 => 22547)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/css/media-views.css        2012-11-11 22:58:32 UTC (rev 22546)
+++ trunk/wp-includes/css/media-views.css        2012-11-12 05:57:12 UTC (rev 22547)
</span><span class="lines">@@ -1,4 +1,21 @@
</span><span class="cx"> /**
</span><ins>+ * Base Styles
+ */
+
+.media-frame input,
+.media-frame textarea {
+        padding: 6px 8px;
+        line-height: 16px;
+}
+
+.media-frame select,
+.wp-admin .media-frame select {
+        height: 28px;
+        line-height: 28px;
+        margin-top: 3px;
+}
+
+/**
</ins><span class="cx"> * Modal
</span><span class="cx"> */
</span><span class="cx"> .media-modal {
</span><span class="lines">@@ -96,6 +113,7 @@
</span><span class="cx">         left: 200px;
</span><span class="cx">         bottom: 0;
</span><span class="cx">         border-width: 1px 0 0 0;
</span><ins>+        box-shadow: 0 -4px 4px -4px rgba( 0, 0, 0, 0.1 );
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> .media-frame.hide-toolbar > .media-toolbar {
</span><span class="lines">@@ -217,14 +235,6 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> .media-sidebar .setting input,
</span><del>-.media-sidebar .setting textarea,
-.compat-item .field input,
-.compat-item .field textarea {
-        padding: 6px 8px;
-        line-height: 16px;
-}
-
-.media-sidebar .setting input,
</del><span class="cx"> .media-sidebar .setting textarea {
</span><span class="cx">         width: 65%;
</span><span class="cx">         float: right;
</span><span class="lines">@@ -236,10 +246,7 @@
</span><span class="cx">         resize: none;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-.media-sidebar .setting select,
-.compat-item .field select {
-        height: 28px;
-        line-height: 28px;
</del><ins>+.media-sidebar select {
</ins><span class="cx">         margin-top: 3px;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -984,4 +991,97 @@
</span><span class="cx">
</span><span class="cx"> .gallery-settings {
</span><span class="cx">         overflow: hidden;
</span><ins>+}
+
+/**
+ * Embed from URL
+ */
+.embed-url {
+        display: block;
+        position: relative;
+        height: 75px;
+        padding: 16px 16px;
+        margin: 0;
+        z-index: 50;
+        border-bottom: 1px solid #dfdfdf;
+        box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.1 );
+        font-size: 18px;
+        font-weight: 200;
+}
+
+.embed-url span {
+        display: block;
+        padding: 4px 0 6px 2px;
+}
+
+.embed-url input {
+        padding: 12px 14px;
+        width: 100%;
+        min-width: 200px;
+        /*max-width: 500px;*/
+        box-shadow: inset 2px 2px 4px -2px rgba( 0, 0, 0, 0.1 );
+}
+
+.embed-link-settings,
+.embed-image-settings {
+        position: absolute;
+        background: #f5f5f5;
+        top: 108px;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        padding: 16px 16px 32px;
+        overflow: auto;
+}
+
+.media-embed .thumbnail {
+        max-width: 100%;
+        max-height: 200px;
+        position: relative;
+        float: left;
+}
+
+.media-embed .thumbnail img {
+        max-height: 200px;
+}
+
+.media-embed .thumbnail:after {
+        content: '';
+        display: block;
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        box-shadow: inset 0 0 0 1px rgba( 0, 0, 0, 0.1 );
+        overflow: hidden;
+}
+
+.media-embed .setting {
+        width: 100%;
+        margin-top: 10px;
+        float: left;
+        display: block;
+        clear: both;
+}
+
+.media-embed .setting span {
+        display: block;
+        width: 200px;
+        font-size: 13px;
+        line-height: 24px;
+        color: #999;
+        text-shadow: 0 1px 0 #fff;
+}
+
+.media-embed .setting .button-group {
+        margin: 2px 0;
+}
+
+.media-embed .setting input,
+.media-embed .setting textarea {
+        display: block;
+        width: 100%;
+        max-width: 400px;
+        margin: 1px 0;
</ins><span class="cx"> }
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpincludesjsmediaviewsjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/js/media-views.js (22546 => 22547)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/js/media-views.js        2012-11-11 22:58:32 UTC (rev 22546)
+++ trunk/wp-includes/js/media-views.js        2012-11-12 05:57:12 UTC (rev 22547)
</span><span class="lines">@@ -316,17 +316,19 @@
</span><span class="cx">                 },
</span><span class="cx">
</span><span class="cx">                 deactivate: function() {
</span><del>-                        this.off( 'change:library change:exclude', this.buildComposite, this );
-                        this.off( 'change:excludeState', this._excludeState, this );
-                        this.destroyComposite();
</del><ins>+                        this.off( 'change:empty', this.refresh, this );
+                        this.get('library').off( 'add remove reset', this._updateEmpty, this );
</ins><span class="cx">
</span><del>-                        wp.Uploader.queue.off( 'add', this.selectUpload, this );
-
</del><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><del>-                        this.get('library').off( 'add remove reset', this._updateEmpty, this );
-                        this.off( 'change:empty', this.refresh, this );
</del><ins>+
+                        wp.Uploader.queue.off( 'add', this.selectUpload, this );
+
+                        this.off( 'change:excludeState', this._excludeState, this );
+                        this.off( 'change:library change:exclude', this.buildComposite, this );
+
+                        this.destroyComposite();
</ins><span class="cx">                 },
</span><span class="cx">
</span><span class="cx">                 reset: function() {
</span><span class="lines">@@ -525,6 +527,44 @@
</span><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx">
</span><ins>+
+        // wp.media.controller.Embed
+        // -------------------------
+        media.controller.Embed = media.controller.State.extend({
+                defaults: {
+                        id: 'embed',
+                        url: '',
+                        menu: 'main',
+                        content: 'embed',
+                        toolbar: 'main-embed',
+                        type: 'link'
+                },
+
+                initialize: function() {
+                        this.on( 'change:url', this.scan, this );
+                        media.controller.State.prototype.initialize.apply( this, arguments );
+                },
+
+                scan: function() {
+                        var attributes = { type: 'link' };
+
+                        if ( /(?:jpe?g|png|gif)$/i.test( this.get('url') ) )
+                                attributes.type = 'image';
+
+                        this.trigger( 'scan', attributes );
+                        this.set( attributes );
+                },
+
+                reset: function() {
+                        _.each( _.without( _.keys( this.attributes ), _.keys( this.defaults ) ), function( key ) {
+                                this.unset( key );
+                        }, this );
+
+                        this.set( 'url', '' );
+                        this.frame.toolbar.view().refresh();
+                }
+        });
+
</ins><span class="cx">         /**
</span><span class="cx">          * ========================================================================
</span><span class="cx">          * VIEWS
</span><span class="lines">@@ -858,9 +898,17 @@
</span><span class="cx">                 },
</span><span class="cx">
</span><span class="cx">                 // Toolbars
</span><del>-                selectToolbar: function() {
</del><ins>+                selectToolbar: function( options ) {
+                        options = _.defaults( options || {}, {
+                                event: 'select',
+                                silent: false,
+                                state: false
+                        });
+
</ins><span class="cx">                         this.toolbar.view( new media.view.Toolbar({
</span><span class="cx">                                 controller: this,
</span><ins>+                                silent: options.silent,
+
</ins><span class="cx">                                 items: {
</span><span class="cx">                                         select: {
</span><span class="cx">                                                 style: 'primary',
</span><span class="lines">@@ -871,8 +919,10 @@
</span><span class="cx">                                                         var controller = this.controller;
</span><span class="cx">
</span><span class="cx">                                                         controller.close();
</span><del>-                                                        controller.state().trigger('select');
-                                                        controller.reset().state( controller.options.state );
</del><ins>+                                                        controller.state().trigger( options.event );
+                                                        controller.reset();
+                                                        if ( options.state )
+                                                                controller.state( options.state );
</ins><span class="cx">                                                 }
</span><span class="cx">                                         }
</span><span class="cx">                                 }
</span><span class="lines">@@ -941,6 +991,9 @@
</span><span class="cx">
</span><span class="cx">                                 new media.controller.Upload( main ),
</span><span class="cx">
</span><ins>+                                // Embed states.
+                                new media.controller.Embed(),
+
</ins><span class="cx">                                 // Gallery states.
</span><span class="cx">                                 new media.controller.Gallery({
</span><span class="cx">                                         library: options.selection,
</span><span class="lines">@@ -991,7 +1044,7 @@
</span><span class="cx">                                         },
</span><span class="cx">
</span><span class="cx">                                         content: {
</span><del>-                                                embed: 'embedContent'
</del><ins>+                                                embed: 'embedContent'
</ins><span class="cx">                                         },
</span><span class="cx">
</span><span class="cx">                                         sidebar: {
</span><span class="lines">@@ -1121,12 +1174,24 @@
</span><span class="cx">                 },
</span><span class="cx">
</span><span class="cx">                 // Content
</span><del>-                embedContent: function() {},
</del><ins>+                embedContent: function() {
+                        var view = new media.view.Embed({
+                                controller: this,
+                                model: this.state()
+                        }).render();
</ins><span class="cx">
</span><ins>+                        this.$el.addClass('hide-sidebar');
+                        this.content.view( view );
+                        view.url.focus();
+                },
+
</ins><span class="cx">                 // Sidebars
</span><span class="cx">                 onSidebarGallerySettings: function( options ) {
</span><span class="cx">                         var library = this.state().get('library');
</span><span class="cx">
</span><ins>+                        if ( ! library )
+                                return;
+
</ins><span class="cx">                         library.gallery = library.gallery || new Backbone.Model();
</span><span class="cx">
</span><span class="cx">                         this.sidebar.view().add({
</span><span class="lines">@@ -1169,8 +1234,14 @@
</span><span class="cx">                         }) );
</span><span class="cx">                 },
</span><span class="cx">
</span><del>-                mainEmbedToolbar: function() {},
</del><ins>+                mainEmbedToolbar: function() {
+                        this.toolbar.view( new media.view.Toolbar.Embed({
+                                controller: this
+                        }) );
</ins><span class="cx">
</span><ins>+                        this.$el.removeClass('hide-toolbar');
+                },
+
</ins><span class="cx">                 batchEditToolbar: function() {
</span><span class="cx">                         this.toolbar.view( new media.view.Toolbar({
</span><span class="cx">                                 controller: this,
</span><span class="lines">@@ -1495,7 +1566,7 @@
</span><span class="cx">                         this.$secondary = $('<div class="media-toolbar-secondary" />').prependTo( this.$el );
</span><span class="cx">
</span><span class="cx">                         if ( this.options.items )
</span><del>-                                this.add( this.options.items, { silent: true });
</del><ins>+                                this.set( this.options.items, { silent: true });
</ins><span class="cx">
</span><span class="cx">                         if ( ! this.options.silent )
</span><span class="cx">                                 this.render();
</span><span class="lines">@@ -1503,6 +1574,15 @@
</span><span class="cx">
</span><span class="cx">                 destroy: function() {
</span><span class="cx">                         this.remove();
</span><ins>+
+                        if ( this.model )
+                                this.model.off( null, null, this );
+
+                        if ( this.collection )
+                                this.collection.off( null, null, this );
+
+                        this.controller.off( null, null, this );
+
</ins><span class="cx">                         _.each( this._views, function( view ) {
</span><span class="cx">                                 if ( view.destroy )
</span><span class="cx">                                         view.destroy();
</span><span class="lines">@@ -1527,28 +1607,26 @@
</span><span class="cx">                         return this;
</span><span class="cx">                 },
</span><span class="cx">
</span><del>-                add: function( id, view, options ) {
</del><ins>+                set: function( id, view, options ) {
</ins><span class="cx">                         options = options || {};
</span><span class="cx">
</span><span class="cx">                         // Accept an object with an `id` : `view` mapping.
</span><span class="cx">                         if ( _.isObject( id ) ) {
</span><span class="cx">                                 _.each( id, function( view, id ) {
</span><del>-                                        this.add( id, view, { silent: true });
</del><ins>+                                        this.set( id, view, { silent: true });
</ins><span class="cx">                                 }, this );
</span><span class="cx">
</span><del>-                                if ( ! options.silent )
-                                        this.render();
-                                return this;
-                        }
</del><ins>+                        } else {
+                                if ( ! ( view instanceof Backbone.View ) ) {
+                                        view.classes = [ id ].concat( view.classes || [] );
+                                        view = new media.view.Button( view ).render();
+                                }
</ins><span class="cx">
</span><del>-                        if ( ! ( view instanceof Backbone.View ) ) {
-                                view.classes = [ id ].concat( view.classes || [] );
-                                view = new media.view.Button( view ).render();
</del><ins>+                                view.controller = view.controller || this.controller;
+
+                                this._views[ id ] = view;
</ins><span class="cx">                         }
</span><span class="cx">
</span><del>-                        view.controller = view.controller || this.controller;
-
-                        this._views[ id ] = view;
</del><span class="cx">                         if ( ! options.silent )
</span><span class="cx">                                 this.render();
</span><span class="cx">                         return this;
</span><span class="lines">@@ -1558,7 +1636,7 @@
</span><span class="cx">                         return this._views[ id ];
</span><span class="cx">                 },
</span><span class="cx">
</span><del>-                remove: function( id, options ) {
</del><ins>+                unset: function( id, options ) {
</ins><span class="cx">                         delete this._views[ id ];
</span><span class="cx">                         if ( ! options || ! options.silent )
</span><span class="cx">                                 this.render();
</span><span class="lines">@@ -1568,8 +1646,76 @@
</span><span class="cx">                 refresh: function() {}
</span><span class="cx">         });
</span><span class="cx">
</span><ins>+        // wp.media.view.Toolbar.Select
+        // ----------------------------
+        media.view.Toolbar.Select = media.view.Toolbar.extend({
+                initialize: function() {
+                        var options = this.options,
+                                controller = options.controller,
+                                selection = controller.state().get('selection');
+
+                        _.bindAll( this, 'clickSelect' );
+
+                        _.defaults( options, {
+                                event: 'select',
+                                state: false,
+                                reset: true,
+                                close: true,
+                                text: l10n.select
+                        });
+
+                        options.items = _.defaults( options.items || {}, {
+                                select: {
+                                        style: 'primary',
+                                        text: options.text,
+                                        priority: 80,
+                                        click: this.clickSelect
+                                }
+                        });
+
+                        media.view.Toolbar.prototype.initialize.apply( this, arguments );
+                },
+
+                clickSelect: function() {
+                        var options = this.options,
+                                controller = this.controller;
+
+                        if ( options.close )
+                                controller.close();
+
+                        if ( options.event )
+                                controller.state().trigger( options.event );
+
+                        if ( options.reset )
+                                controller.reset();
+
+                        if ( options.state )
+                                controller.state( options.state );
+                }
+        });
+
+        // wp.media.view.Toolbar.Embed
+        // ---------------------------
+        media.view.Toolbar.Embed = media.view.Toolbar.Select.extend({
+                initialize: function() {
+                        var controller = this.options.controller;
+
+                        _.defaults( this.options, {
+                                text: l10n.insertEmbed
+                        });
+
+                        media.view.Toolbar.Select.prototype.initialize.apply( this, arguments );
+                        controller.on( 'change:url', this.refresh, this );
+                },
+
+                refresh: function() {
+                        var url = this.controller.state().get('url');
+                        this.get('select').model.set( 'disabled', ! url || /^https?:\/\/$/.test(url) );
+                }
+        });
+
</ins><span class="cx">         // wp.media.view.Toolbar.Insert
</span><del>-        // ---------------------------------
</del><ins>+        // ----------------------------
</ins><span class="cx">         media.view.Toolbar.Insert = media.view.Toolbar.extend({
</span><span class="cx">                 initialize: function() {
</span><span class="cx">                         var controller = this.options.controller,
</span><span class="lines">@@ -1886,6 +2032,7 @@
</span><span class="cx">
</span><span class="cx">                 click: function() {
</span><span class="cx">                         var options = this.options;
</span><ins>+
</ins><span class="cx">                         if ( options.click )
</span><span class="cx">                                 options.click.call( this );
</span><span class="cx">                         else if ( options.id )
</span><span class="lines">@@ -2344,7 +2491,7 @@
</span><span class="cx">                         });
</span><span class="cx">
</span><span class="cx">                         if ( this.options.search ) {
</span><del>-                                this.toolbar.add( 'search', new media.view.Search({
</del><ins>+                                this.toolbar.set( 'search', new media.view.Search({
</ins><span class="cx">                                         controller: this.controller,
</span><span class="cx">                                         model: this.collection.props,
</span><span class="cx">                                         priority: -60
</span><span class="lines">@@ -2352,7 +2499,7 @@
</span><span class="cx">                         }
</span><span class="cx">
</span><span class="cx">                         if ( this.options.sortable ) {
</span><del>-                                this.toolbar.add( 'dragInfo', new Backbone.View({
</del><ins>+                                this.toolbar.set( 'dragInfo', new Backbone.View({
</ins><span class="cx">                                         el: $( '<div class="instructions">' + l10n.dragInfo + '</div>' )[0],
</span><span class="cx">                                         priority: -40
</span><span class="cx">                                 }) );
</span><span class="lines">@@ -2564,6 +2711,11 @@
</span><span class="cx">                         } else if ( $setting.hasClass('button-group') ) {
</span><span class="cx">                                 $buttons = $setting.find('button').removeClass('active');
</span><span class="cx">                                 $buttons.filter( '[value="' + value + '"]' ).addClass('active');
</span><ins>+
+                        // Handle text inputs and textareas.
+                        } else if ( $setting.is('input[type="text"], textarea') ) {
+                                if ( ! $setting.is(':focus') )
+                                        $setting.val( value );
</ins><span class="cx">                         }
</span><span class="cx">                 },
</span><span class="cx">
</span><span class="lines">@@ -2718,4 +2870,138 @@
</span><span class="cx">                         return this;
</span><span class="cx">                 }
</span><span class="cx">         });
</span><ins>+
+        /**
+         * wp.media.view.Embed
+         */
+        media.view.Embed = Backbone.View.extend({
+                className: 'media-embed',
+
+                initialize: function() {
+                        this.controller = this.options.controller;
+
+                        this.url = new media.view.EmbedUrl({
+                                controller: this.controller,
+                                model: this.model
+                        }).render();
+
+                        this._settings = new Backbone.View();
+                        this.refresh();
+                        this.model.on( 'change:type', this.refresh, this );
+                },
+
+                render: function() {
+                        this.$el.html([ this.url.el, this._settings.el ]);
+                        this.url.focus();
+                        return this;
+                },
+
+                settings: function( view ) {
+                        view.render();
+                        this._settings.$el.replaceWith( view.$el );
+                        if ( this._settings.destroy )
+                                this._settings.destroy();
+                        this._settings.remove();
+                        this._settings = view;
+                },
+
+                refresh: function() {
+                        var type = this.model.get('type'),
+                                constructor;
+
+                        if ( 'image' === type )
+                                constructor = media.view.EmbedImage;
+                        else if ( 'link' === type )
+                                constructor = media.view.EmbedLink;
+                        else
+                                return;
+
+                        this.settings( new constructor({
+                                controller: this.controller,
+                                model: this.model,
+                                priority: 40
+                        }) );
+                }
+        });
+
+        /**
+         * wp.media.view.EmbedUrl
+         */
+        media.view.EmbedUrl = Backbone.View.extend({
+                tagName: 'label',
+                className: 'embed-url',
+
+                events: {
+                        'keyup': 'url'
+                },
+
+                initialize: function() {
+                        this.label = this.make( 'span', null, this.options.label || l10n.url );
+                        this.input = this.make( 'input', {
+                                type: 'text',
+                                value: this.model.get('url') || ''
+                        });
+
+                        this.$label = $( this.label );
+                        this.$input = $( this.input );
+                        this.$el.append([ this.label, this.input ]);
+
+                        this.model.on( 'change:url', this.render, this );
+                },
+
+                destroy: function() {
+                        this.model.off( null, null, this );
+                },
+
+                render: function() {
+                        var $input = this.$input;
+
+                        if ( $input.is(':focus') )
+                                return;
+
+                        this.input.value = this.model.get('url') || 'http://';
+                        return this;
+                },
+
+                url: function( event ) {
+                        this.model.set( 'url', event.target.value );
+                },
+
+                focus: function() {
+                        var $input = this.$input;
+                        // If the input is visible, focus and select its contents.
+                        if ( $input.is(':visible') )
+                                $input.focus()[0].select();
+                }
+        });
+
+        /**
+         * wp.media.view.EmbedLink
+         */
+        media.view.EmbedLink = media.view.Settings.extend({
+                className: 'embed-link-settings',
+                template: media.template('embed-link-settings')
+        });
+
+        /**
+         * wp.media.view.EmbedImage
+         */
+        media.view.EmbedImage = media.view.Settings.AttachmentDisplay.extend({
+                className: 'embed-image-settings',
+                template: media.template('embed-image-settings'),
+
+                initialize: function() {
+                        media.view.Settings.AttachmentDisplay.prototype.initialize.apply( this, arguments );
+                        this.model.on( 'change:url', this.updateImage, this );
+                },
+
+                destroy: function() {
+                        this.model.off( null, null, this );
+                        media.view.Settings.AttachmentDisplay.prototype.destroy.apply( this, arguments );
+                },
+
+                updateImage: function() {
+                        this.$('img').attr( 'src', this.model.get('url') );
+                }
+        });
</ins><span class="cx"> }(jQuery));
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpincludesmediaphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/media.php (22546 => 22547)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/media.php        2012-11-11 22:58:32 UTC (rev 22546)
+++ trunk/wp-includes/media.php        2012-11-12 05:57:12 UTC (rev 22547)
</span><span class="lines">@@ -1326,6 +1326,7 @@
</span><span class="cx">                 'settings' => $settings,
</span><span class="cx">
</span><span class="cx">                 // Generic
</span><ins>+                'url' => __( 'URL' ),
</ins><span class="cx">                 'insertMedia' => __( 'Insert Media' ),
</span><span class="cx">                 'search' => __( 'Search' ),
</span><span class="cx">                 'select' => __( 'Select' ),
</span><span class="lines">@@ -1346,6 +1347,7 @@
</span><span class="cx">
</span><span class="cx">                 // Embed
</span><span class="cx">                 'embedFromUrlTitle' => __( 'Embed From URL' ),
</span><ins>+                'insertEmbed' => __( 'Insert embed' ),
</ins><span class="cx">
</span><span class="cx">                 // Batch
</span><span class="cx">                 'batchInsert' => __( 'Batch insert' ),
</span><span class="lines">@@ -1570,7 +1572,7 @@
</span><span class="cx">                         <input type="text" class="link-to-custom" data-setting="linkUrl" />
</span><span class="cx">                 </div>
</span><span class="cx">
</span><del>-                <# if ( ! _.isUndefined( sizes ) ) { #>
</del><ins>+                <# if ( 'undefined' !== typeof sizes ) { #>
</ins><span class="cx">                         <label class="setting">
</span><span class="cx">                                 <span><?php _e('Size'); ?></span>
</span><span class="cx">                                 <select class="size" name="size"
</span><span class="lines">@@ -1587,7 +1589,7 @@
</span><span class="cx">                                         ) );
</span><span class="cx">
</span><span class="cx">                                         foreach ( $sizes as $value => $name ) : ?>
</span><del>-                                                <# if ( ! _.isUndefined( sizes['<?php echo esc_js( $value ); ?>'] ) ) { #>
</del><ins>+                                                <# if ( sizes['<?php echo esc_js( $value ); ?>'] ) { #>
</ins><span class="cx">                                                         <option value="<?php echo esc_attr( $value ); ?>" <?php selected( $value, 'medium' ); ?>>
</span><span class="cx">                                                                 <?php echo esc_html( $name ); ?>
</span><span class="cx">                                                         </option>
</span><span class="lines">@@ -1635,6 +1637,63 @@
</span><span class="cx">                 </label>
</span><span class="cx">         </script>
</span><span class="cx">
</span><ins>+        <script type="text/html" id="tmpl-embed-link-settings">
+                <label class="setting">
+                        <span><?php _e('Title'); ?></span>
+                        <input type="text" class="alignment" data-setting="title" />
+                </label>
+        </script>
+
+        <script type="text/html" id="tmpl-embed-image-settings">
+                <div class="thumbnail">
+                        <img src="{{ model.url }}" draggable="false" />
+                </div>
+
+                <label class="setting caption">
+                        <span><?php _e('Caption'); ?></span>
+                        <textarea data-setting="caption" />
+                </label>
+
+                <label class="setting alt-text">
+                        <span><?php _e('Alt Text'); ?></span>
+                        <input type="text" data-setting="alt" />
+                </label>
+
+                <label class="setting align">
+                        <span><?php _e('Align'); ?></span>
+                        <div class="button-group button-large" data-setting="align">
+                                <button class="button" value="left">
+                                        <?php esc_attr_e('Left'); ?>
+                                </button>
+                                <button class="button" value="center">
+                                        <?php esc_attr_e('Center'); ?>
+                                </button>
+                                <button class="button" value="right">
+                                        <?php esc_attr_e('Right'); ?>
+                                </button>
+                                <button class="button active" value="none">
+                                        <?php esc_attr_e('None'); ?>
+                                </button>
+                        </div>
+                </label>
+
+                <div class="setting link-to">
+                        <span><?php _e('Link To'); ?></span>
+                        <div class="button-group button-large" data-setting="link">
+                                <button class="button" value="file">
+                                        <?php esc_attr_e('Image URL'); ?>
+                                </button>
+                                <button class="button" value="custom">
+                                        <?php esc_attr_e('Custom URL'); ?>
+                                </button>
+                                <button class="button active" value="none">
+                                        <?php esc_attr_e('None'); ?>
+                                </button>
+                        </div>
+                        <input type="text" class="link-to-custom" data-setting="linkUrl" />
+                </div>
+        </script>
+
</ins><span class="cx">         <script type="text/html" id="tmpl-editor-attachment">
</span><span class="cx">                 <div class="editor-attachment-preview">
</span><span class="cx">                         <# if ( url ) { #>
</span></span></pre>
</div>
</div>
</body>
</html>