<!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>[22567] trunk: Media: Restore 3.4 editor behavior and remove TinyMCE views.</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/22567">22567</a></dd>
<dt>Author</dt> <dd>koopersmith</dd>
<dt>Date</dt> <dd>2012-11-14 07:17:22 +0000 (Wed, 14 Nov 2012)</dd>
</dl>

<h3>Log Message</h3>
<pre>Media: Restore 3.4 editor behavior and remove TinyMCE views.

* Reactivates the `wpgallery` and `wpeditimage` TinyMCE plugins. Deactivates the `wpviews` TinyMCE plugin.
* Moves still-relevant logic from `mce-views.js` to `media-upload.js` and `shortcode.js`.
* No longer include `wp-includes/js/mce-views.js`. This code will not be used in 3.5, and should be considered unstable.
* Currently, this is the real 3.4 experience; as such, editing triggers the old modals. Changing this is the next major step.

When reassessing views, we should look over all of these tickets and anticipate these bugs accordingly.

fixes <a href="http://core.trac.wordpress.org/ticket/21813">#21813</a>, <a href="http://core.trac.wordpress.org/ticket/22123">#22123</a>, <a href="http://core.trac.wordpress.org/ticket/22155">#22155</a>, <a href="http://core.trac.wordpress.org/ticket/22161">#22161</a>, <a href="http://core.trac.wordpress.org/ticket/22257">#22257</a>, <a href="http://core.trac.wordpress.org/ticket/22266">#22266</a>, <a href="http://core.trac.wordpress.org/ticket/22318">#22318</a>, <a href="http://core.trac.wordpress.org/ticket/22407">#22407</a>, see <a href="http://core.trac.wordpress.org/ticket/21390">#21390</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpadminjsmediauploadjs">trunk/wp-admin/js/media-upload.js</a></li>
<li><a href="#trunkwpincludesclasswpeditorphp">trunk/wp-includes/class-wp-editor.php</a></li>
<li><a href="#trunkwpincludesjsmceviewjs">trunk/wp-includes/js/mce-view.js</a></li>
<li><a href="#trunkwpincludesjsshortcodejs">trunk/wp-includes/js/shortcode.js</a></li>
<li><a href="#trunkwpincludesscriptloaderphp">trunk/wp-includes/script-loader.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpadminjsmediauploadjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/js/media-upload.js (22566 => 22567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/js/media-upload.js        2012-11-14 05:29:56 UTC (rev 22566)
+++ trunk/wp-admin/js/media-upload.js        2012-11-14 07:17:22 UTC (rev 22567)
</span><span class="lines">@@ -90,10 +90,204 @@
</span><span class="cx"> // WordPress, TinyMCE, and Media
</span><span class="cx"> // -----------------------------
</span><span class="cx"> (function($){
</span><del>-        // Stores the editors' `wp.media.controller.Workflow` instances.
-        var workflows = {};
</del><ins>+        // Stores the editors' `wp.media.controller.Frame` instances.
+        var workflows = {},
+                linkToUrl;
</ins><span class="cx"> 
</span><del>-        wp.mce.media = {
</del><ins>+        linkToUrl = function( attachment, props ) {
+                var link = props.link,
+                        url;
+
+                if ( 'file' === link )
+                        url = attachment.get('url');
+                else if ( 'post' === link )
+                        url = attachment.get('link');
+                else if ( 'custom' === link )
+                        url = props.linkUrl;
+
+                return url || '';
+        };
+
+        wp.media.string = {};
+
+        wp.media.string.link = function( attachment, props ) {
+                var linkTo  = getUserSetting( 'urlbutton', 'post' ),
+                        options = {
+                                tag:     'a',
+                                content: attachment.get('title') || attachment.get('filename'),
+                                attrs:   {
+                                        rel: 'attachment wp-att-' + attachment.id
+                                }
+                        };
+
+                options.attrs.href = linkToUrl( attachment, props );
+
+                return wp.html.string( options );
+        };
+
+        wp.media.string.image = function( attachment, props ) {
+                var classes, img, options, size, shortcode, html;
+
+                props = _.defaults( props || {}, {
+                        img:   {},
+                        align: getUserSetting( 'align', 'none' ),
+                        size:  getUserSetting( 'imgsize', 'medium' ),
+                        link:  getUserSetting( 'urlbutton', 'post' )
+                });
+
+                props.linkUrl = linkToUrl( attachment, props );
+
+                attachment = attachment.toJSON();
+
+                img     = _.clone( props.img );
+                classes = img['class'] ? img['class'].split(/\s+/) : [];
+                size    = attachment.sizes ? attachment.sizes[ props.size ] : {};
+
+                if ( ! size ) {
+                        delete props.size;
+                        size = attachment;
+                }
+
+                img.width  = size.width;
+                img.height = size.height;
+                img.src    = size.url;
+
+                // Only assign the align class to the image if we're not printing
+                // a caption, since the alignment is sent to the shortcode.
+                if ( props.align &amp;&amp; ! attachment.caption )
+                        classes.push( 'align' + props.align );
+
+                if ( props.size )
+                        classes.push( 'size-' + props.size );
+
+                classes.push( 'wp-image-' + attachment.id );
+
+                img['class'] = _.compact( classes ).join(' ');
+
+                // Generate `img` tag options.
+                options = {
+                        tag:    'img',
+                        attrs:  img,
+                        single: true
+                };
+
+                // Generate the `href` based on the `link` property.
+                if ( props.linkUrl ) {
+                        props.anchor = props.anchor || {};
+                        props.anchor.href = props.linkUrl;
+                }
+
+                // Generate the `a` element options, if they exist.
+                if ( props.anchor ) {
+                        options = {
+                                tag:     'a',
+                                attrs:   props.anchor,
+                                content: options
+                        };
+                }
+
+                html = wp.html.string( options );
+
+                // Generate the caption shortcode.
+                if ( attachment.caption ) {
+                        shortcode = {
+                                id:    'attachment_' + attachment.id,
+                                width: img.width
+                        };
+
+                        if ( props.align )
+                                shortcode.align = 'align' + props.align;
+
+                        html = wp.shortcode.string({
+                                tag:     'caption',
+                                attrs:   shortcode,
+                                content: html + ' ' + attachment.caption
+                        });
+                }
+
+                return html;
+        };
+
+        wp.media.gallery = (function() {
+                var galleries = {};
+
+                return {
+                        attachments: function( shortcode, parent ) {
+                                var shortcodeString = shortcode.string(),
+                                        result = galleries[ shortcodeString ],
+                                        attrs, args, query, others;
+
+                                delete galleries[ shortcodeString ];
+
+                                if ( result )
+                                        return result;
+
+                                attrs = shortcode.attrs.named;
+                                args  = _.pick( attrs, 'orderby', 'order' );
+
+                                args.type    = 'image';
+                                args.perPage = -1;
+
+                                // Map the `ids` param to the correct query args.
+                                if ( attrs.ids ) {
+                                        args.post__in = attrs.ids.split(',');
+                                        args.orderby  = 'post__in';
+                                } else if ( attrs.include ) {
+                                        args.post__in = attrs.include.split(',');
+                                }
+
+                                if ( attrs.exclude )
+                                        args.post__not_in = attrs.exclude.split(',');
+
+                                if ( ! args.post__in )
+                                        args.parent = attrs.id || parent;
+
+                                // Collect the attributes that were not included in `args`.
+                                others = {};
+                                _.filter( attrs, function( value, key ) {
+                                        if ( _.isUndefined( args[ key ] ) )
+                                                others[ key ] = value;
+                                });
+
+                                query = media.query( args );
+                                query.gallery = new Backbone.Model( others );
+                                return query;
+                        },
+
+                        shortcode: function( attachments ) {
+                                var props = attachments.props.toJSON(),
+                                        attrs = _.pick( props, 'include', 'exclude', 'orderby', 'order' ),
+                                        shortcode, clone;
+
+                                if ( attachments.gallery )
+                                        _.extend( attrs, attachments.gallery.toJSON() );
+
+                                attrs.ids = attachments.pluck('id');
+
+                                // If the `ids` attribute is set and `orderby` attribute
+                                // is the default value, clear it for cleaner output.
+                                if ( attrs.ids &amp;&amp; 'post__in' === attrs.orderby )
+                                        delete attrs.orderby;
+
+                                shortcode = new wp.shortcode({
+                                        tag:    'gallery',
+                                        attrs:  attrs,
+                                        type:   'single'
+                                });
+
+                                // Use a cloned version of the gallery.
+                                clone = new wp.media.model.Attachments( attachments.models, {
+                                        props: props
+                                });
+                                clone.gallery = attachments.gallery;
+                                galleries[ shortcode.string() ] = clone;
+
+                                return shortcode;
+                        }
+                };
+        }());
+
+        wp.media.editor = {
</ins><span class="cx">                 insert: send_to_editor,
</span><span class="cx"> 
</span><span class="cx">                 add: function( id, options ) {
</span><span class="lines">@@ -134,14 +328,7 @@
</span><span class="cx">                         }, this );
</span><span class="cx"> 
</span><span class="cx">                         workflow.get('gallery-edit').on( 'update', function( selection ) {
</span><del>-                                var view = wp.mce.view.get('gallery'),
-                                        shortcode;
-
-                                if ( ! view )
-                                        return;
-
-                                shortcode = view.gallery.shortcode( selection );
-                                this.insert( shortcode.string() );
</del><ins>+                                this.insert( wp.media.gallery.shortcode( selection ).string() );
</ins><span class="cx">                         }, this );
</span><span class="cx"> 
</span><span class="cx">                         workflow.get('embed').on( 'select', function() {
</span><span class="lines">@@ -211,7 +398,7 @@
</span><span class="cx">                                 if ( ! editor )
</span><span class="cx">                                         return;
</span><span class="cx"> 
</span><del>-                                workflow = wp.mce.media.get( editor );
</del><ins>+                                workflow = wp.media.editor.get( editor );
</ins><span class="cx"> 
</span><span class="cx">                                 // If the workflow exists, just open it.
</span><span class="cx">                                 if ( workflow ) {
</span><span class="lines">@@ -220,10 +407,10 @@
</span><span class="cx">                                 }
</span><span class="cx"> 
</span><span class="cx">                                 // Initialize the editor's workflow if we haven't yet.
</span><del>-                                wp.mce.media.add( editor );
</del><ins>+                                wp.media.editor.add( editor );
</ins><span class="cx">                         });
</span><span class="cx">                 }
</span><span class="cx">         };
</span><span class="cx"> 
</span><del>-        $( wp.mce.media.init );
</del><ins>+        $( wp.media.editor.init );
</ins><span class="cx"> }(jQuery));
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpincludesclasswpeditorphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/class-wp-editor.php (22566 => 22567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/class-wp-editor.php        2012-11-14 05:29:56 UTC (rev 22566)
+++ trunk/wp-includes/class-wp-editor.php        2012-11-14 07:17:22 UTC (rev 22567)
</span><span class="lines">@@ -191,12 +191,12 @@
</span><span class="cx">                                 self::$baseurl = includes_url('js/tinymce');
</span><span class="cx">                                 self::$mce_locale = $mce_locale = ( '' == get_locale() ) ? 'en' : strtolower( substr(get_locale(), 0, 2) ); // only ISO 639-1
</span><span class="cx">                                 $no_captions = (bool) apply_filters( 'disable_captions', '' );
</span><del>-                                $plugins = array( 'inlinepopups', 'spellchecker', 'tabfocus', 'paste', 'media', 'fullscreen', 'wordpress', 'wplink', 'wpdialogs', 'wpview' );
</del><ins>+                                $plugins = array( 'inlinepopups', 'spellchecker', 'tabfocus', 'paste', 'media', 'fullscreen', 'wordpress', 'wpeditimage', 'wpgallery', 'wplink', 'wpdialogs' );
</ins><span class="cx">                                 $first_run = true;
</span><span class="cx">                                 $ext_plugins = '';
</span><span class="cx"> 
</span><span class="cx">                                 if ( $set['teeny'] ) {
</span><del>-                                        self::$plugins = $plugins = apply_filters( 'teeny_mce_plugins', array('inlinepopups', 'fullscreen', 'wordpress', 'wplink', 'wpdialogs', 'wpview'), $editor_id );
</del><ins>+                                        self::$plugins = $plugins = apply_filters( 'teeny_mce_plugins', array('inlinepopups', 'fullscreen', 'wordpress', 'wplink', 'wpdialogs' ), $editor_id );
</ins><span class="cx">                                 } else {
</span><span class="cx">                                         /*
</span><span class="cx">                                         The following filter takes an associative array of external plugins for TinyMCE in the form 'plugin_name' =&gt; 'url'.
</span></span></pre></div>
<a id="trunkwpincludesjsmceviewjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/js/mce-view.js (22566 => 22567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/js/mce-view.js        2012-11-14 05:29:56 UTC (rev 22566)
+++ trunk/wp-includes/js/mce-view.js        2012-11-14 07:17:22 UTC (rev 22567)
</span><span class="lines">@@ -1,72 +1,6 @@
</span><span class="cx"> // Ensure the global `wp` object exists.
</span><span class="cx"> window.wp = window.wp || {};
</span><span class="cx"> 
</span><del>-// HTML utility functions
-// ----------------------
-(function(){
-        wp.html = _.extend( wp.html || {}, {
-                // ### Parse HTML attributes.
-                //
-                // Converts `content` to a set of parsed HTML attributes.
-                // Utilizes `wp.shortcode.attrs( content )`, which is a valid superset of
-                // the HTML attribute specification. Reformats the attributes into an
-                // object that contains the `attrs` with `key:value` mapping, and a record
-                // of the attributes that were entered using `empty` attribute syntax (i.e.
-                // with no value).
-                attrs: function( content ) {
-                        var result, attrs;
-
-                        // If `content` ends in a slash, strip it.
-                        if ( '/' === content[ content.length - 1 ] )
-                                content = content.slice( 0, -1 );
-
-                        result = wp.shortcode.attrs( content );
-                        attrs  = result.named;
-
-                        _.each( result.numeric, function( key ) {
-                                if ( /\s/.test( key ) )
-                                        return;
-
-                                attrs[ key ] = '';
-                        });
-
-                        return attrs;
-                },
-
-                // ### Convert an HTML-representation of an object to a string.
-                string: function( options ) {
-                        var text = '&lt;' + options.tag,
-                                content = options.content || '';
-
-                        _.each( options.attrs, function( value, attr ) {
-                                text += ' ' + attr;
-
-                                // Use empty attribute notation where possible.
-                                if ( '' === value )
-                                        return;
-
-                                // Convert boolean values to strings.
-                                if ( _.isBoolean( value ) )
-                                        value = value ? 'true' : 'false';
-
-                                text += '=&quot;' + value + '&quot;';
-                        });
-
-                        // Return the result if it is a self-closing tag.
-                        if ( options.single )
-                                return text + ' /&gt;';
-
-                        // Complete the opening tag.
-                        text += '&gt;';
-
-                        // If `content` is an object, recursively call this function.
-                        text += _.isObject( content ) ? wp.html.string( content ) : content;
-
-                        return text + '&lt;/' + options.tag + '&gt;';
-                }
-        });
-}());
-
</del><span class="cx"> (function($){
</span><span class="cx">         var views = {},
</span><span class="cx">                 instances = {};
</span><span class="lines">@@ -409,381 +343,7 @@
</span><span class="cx"> 
</span><span class="cx">                         $node.removeClass('selected');
</span><span class="cx">                         $( node.firstChild ).trigger('deselect');
</span><del>-                },
-
-                // Link any localized strings.
-                l10n: _.isUndefined( _wpMceViewL10n ) ? {} : _wpMceViewL10n
-        };
-
-}(jQuery));
-
-// Default TinyMCE Views
-// ---------------------
-(function($){
-        var mceview = wp.mce.view,
-                linkToUrl;
-
-        linkToUrl = function( attachment, props ) {
-                var link = props.link,
-                        url;
-
-                if ( 'file' === link )
-                        url = attachment.get('url');
-                else if ( 'post' === link )
-                        url = attachment.get('link');
-                else if ( 'custom' === link )
-                        url = props.linkUrl;
-
-                return url || '';
-        };
-
-        wp.media.string = {};
-
-        wp.media.string.link = function( attachment, props ) {
-                var linkTo  = getUserSetting( 'urlbutton', 'post' ),
-                        options = {
-                                tag:     'a',
-                                content: attachment.get('title') || attachment.get('filename'),
-                                attrs:   {
-                                        rel: 'attachment wp-att-' + attachment.id
-                                }
-                        };
-
-                options.attrs.href = linkToUrl( attachment, props );
-
-                return wp.html.string( options );
-        };
-
-        wp.media.string.image = function( attachment, props ) {
-                var classes, img, options, size, shortcode, html;
-
-                props = _.defaults( props || {}, {
-                        img:   {},
-                        align: getUserSetting( 'align', 'none' ),
-                        size:  getUserSetting( 'imgsize', 'medium' ),
-                        link:  getUserSetting( 'urlbutton', 'post' )
-                });
-
-                props.linkUrl = linkToUrl( attachment, props );
-
-                attachment = attachment.toJSON();
-
-                img     = _.clone( props.img );
-                classes = img['class'] ? img['class'].split(/\s+/) : [];
-                size    = attachment.sizes ? attachment.sizes[ props.size ] : {};
-
-                if ( ! size ) {
-                        delete props.size;
-                        size = attachment;
</del><span class="cx">                 }
</span><del>-
-                img.width  = size.width;
-                img.height = size.height;
-                img.src    = size.url;
-
-                // Only assign the align class to the image if we're not printing
-                // a caption, since the alignment is sent to the shortcode.
-                if ( props.align &amp;&amp; ! attachment.caption )
-                        classes.push( 'align' + props.align );
-
-                if ( props.size )
-                        classes.push( 'size-' + props.size );
-
-                classes.push( 'wp-image-' + attachment.id );
-
-                img['class'] = _.compact( classes ).join(' ');
-
-                // Generate `img` tag options.
-                options = {
-                        tag:    'img',
-                        attrs:  img,
-                        single: true
-                };
-
-                // Generate the `href` based on the `link` property.
-                if ( props.linkUrl ) {
-                        props.anchor = props.anchor || {};
-                        props.anchor.href = props.linkUrl;
-                }
-
-                // Generate the `a` element options, if they exist.
-                if ( props.anchor ) {
-                        options = {
-                                tag:     'a',
-                                attrs:   props.anchor,
-                                content: options
-                        };
-                }
-
-                html = wp.html.string( options );
-
-                // Generate the caption shortcode.
-                if ( attachment.caption ) {
-                        shortcode = {
-                                id:    'attachment_' + attachment.id,
-                                width: img.width
-                        };
-
-                        if ( props.align )
-                                shortcode.align = 'align' + props.align;
-
-                        html = wp.shortcode.string({
-                                tag:     'caption',
-                                attrs:   shortcode,
-                                content: html + ' ' + attachment.caption
-                        });
-                }
-
-                return html;
</del><span class="cx">         };
</span><span class="cx"> 
</span><del>-        mceview.add( 'attachment', {
-                pattern: new RegExp( '(?:&lt;a([^&gt;]*)&gt;)?&lt;img([^&gt;]*class=(?:&quot;[^&quot;]*|\'[^\']*)\\bwp-image-(\\d+)[^&gt;]*)&gt;(?:&lt;/a&gt;)?' ),
-
-                text: function( instance ) {
-                        var props = _.pick( instance, 'align', 'size', 'link', 'img', 'anchor' );
-                        return wp.media.string.image( instance.model, props );
-                },
-
-                view: {
-                        className: 'editor-attachment',
-                        template:  media.template('editor-attachment'),
-
-                        events: {
-                                'click .close': 'remove'
-                        },
-
-                        initialize: function() {
-                                var view    = this,
-                                        results = this.options.results,
-                                        id      = results[3],
-                                        className;
-
-                                this.model = wp.media.model.Attachment.get( id );
-
-                                if ( results[1] )
-                                        this.anchor = mceview.attrs( results[1] );
-
-                                this.img  = mceview.attrs( results[2] );
-                                className = this.img['class'];
-
-                                // Strip ID class.
-                                className = className.replace( /(?:^|\s)wp-image-\d+/, '' );
-
-                                // Calculate thumbnail `size` and remove class.
-                                className = className.replace( /(?:^|\s)size-(\S+)/, function( match, size ) {
-                                        view.size = size;
-                                        return '';
-                                });
-
-                                // Calculate `align` and remove class.
-                                className = className.replace( /(?:^|\s)align(left|center|right|none)(?:\s|$)/, function( match, align ) {
-                                        view.align = align;
-                                        return '';
-                                });
-
-                                this.img['class'] = className;
-
-                                this.$el.addClass('spinner');
-                                this.model.fetch().done( _.bind( this.render, this ) );
-                        },
-
-                        render: function() {
-                                var attachment = this.model.toJSON(),
-                                        options;
-
-                                // If we don't have the attachment data, bail.
-                                if ( ! attachment.url )
-                                        return;
-
-                                // Align the wrapper.
-                                if ( this.align )
-                                        this.$wrapper.addClass( 'align' + this.align );
-
-                                // Generate the template options.
-                                options = {
-                                        url: 'image' === attachment.type ? attachment.url : attachment.icon,
-                                        uploading: attachment.uploading
-                                };
-
-                                _.extend( options, wp.media.fit({
-                                        width:    attachment.width,
-                                        height:   attachment.height,
-                                        maxWidth: mceview.l10n.contentWidth
-                                }) );
-
-                                // Use the specified size if it exists.
-                                if ( this.size &amp;&amp; attachment.sizes &amp;&amp; attachment.sizes[ this.size ] )
-                                        _.extend( options, _.pick( attachment.sizes[ this.size ], 'url', 'width', 'height' ) );
-
-                                this.$el.html( this.template( options ) );
-                        }
-                }
-        });
-
-        mceview.add( 'gallery', {
-                shortcode: 'gallery',
-
-                gallery: (function() {
-                        var galleries = {};
-
-                        return {
-                                attachments: function( shortcode, parent ) {
-                                        var shortcodeString = shortcode.string(),
-                                                result = galleries[ shortcodeString ],
-                                                attrs, args, query, others;
-
-                                        delete galleries[ shortcodeString ];
-
-                                        if ( result )
-                                                return result;
-
-                                        attrs = shortcode.attrs.named;
-                                        args  = _.pick( attrs, 'orderby', 'order' );
-
-                                        args.type    = 'image';
-                                        args.perPage = -1;
-
-                                        // Map the `ids` param to the correct query args.
-                                        if ( attrs.ids ) {
-                                                args.post__in = attrs.ids.split(',');
-                                                args.orderby  = 'post__in';
-                                        } else if ( attrs.include ) {
-                                                args.post__in = attrs.include.split(',');
-                                        }
-
-                                        if ( attrs.exclude )
-                                                args.post__not_in = attrs.exclude.split(',');
-
-                                        if ( ! args.post__in )
-                                                args.parent = attrs.id || parent;
-
-                                        // Collect the attributes that were not included in `args`.
-                                        others = {};
-                                        _.filter( attrs, function( value, key ) {
-                                                if ( _.isUndefined( args[ key ] ) )
-                                                        others[ key ] = value;
-                                        });
-
-                                        query = media.query( args );
-                                        query.gallery = new Backbone.Model( others );
-                                        return query;
-                                },
-
-                                shortcode: function( attachments ) {
-                                        var props = attachments.props.toJSON(),
-                                                attrs = _.pick( props, 'include', 'exclude', 'orderby', 'order' ),
-                                                shortcode, clone;
-
-                                        if ( attachments.gallery )
-                                                _.extend( attrs, attachments.gallery.toJSON() );
-
-                                        attrs.ids = attachments.pluck('id');
-
-                                        // If the `ids` attribute is set and `orderby` attribute
-                                        // is the default value, clear it for cleaner output.
-                                        if ( attrs.ids &amp;&amp; 'post__in' === attrs.orderby )
-                                                delete attrs.orderby;
-
-                                        shortcode = new wp.shortcode({
-                                                tag:    'gallery',
-                                                attrs:  attrs,
-                                                type:   'single'
-                                        });
-
-                                        // Use a cloned version of the gallery.
-                                        clone = new wp.media.model.Attachments( attachments.models, {
-                                                props: props
-                                        });
-                                        clone.gallery = attachments.gallery;
-                                        galleries[ shortcode.string() ] = clone;
-
-                                        return shortcode;
-                                }
-                        };
-                }()),
-
-                view: {
-                        className: 'editor-gallery',
-                        template:  media.template('editor-gallery'),
-
-                        // The fallback post ID to use as a parent for galleries that don't
-                        // specify the `ids` or `include` parameters.
-                        //
-                        // Uses the hidden input on the edit posts page by default.
-                        parent: $('#post_ID').val(),
-
-                        events: {
-                                'click .close': 'remove',
-                                'click .edit':  'edit'
-                        },
-
-                        initialize: function() {
-                                this.update();
-                        },
-
-                        update: function() {
-                                var        view = mceview.get('gallery');
-
-                                this.attachments = view.gallery.attachments( this.options.shortcode, this.parent );
-                                this.attachments.more().done( _.bind( this.render, this ) );
-                        },
-
-                        render: function() {
-                                var options, thumbnail, size;
-
-                                if ( ! this.attachments.length )
-                                        return;
-
-                                thumbnail = this.attachments.first().toJSON();
-                                size = thumbnail.sizes &amp;&amp; thumbnail.sizes.thumbnail ? thumbnail.sizes.thumbnail : thumbnail;
-
-                                options = {
-                                        url:         size.url,
-                                        orientation: size.orientation,
-                                        count:       this.attachments.length
-                                };
-
-                                this.$el.html( this.template( options ) );
-                        },
-
-                        edit: function() {
-                                var selection;
-
-                                if ( ! wp.media.view || this.frame )
-                                        return;
-
-                                selection = new wp.media.model.Selection( this.attachments.models, {
-                                        props:    this.attachments.props.toJSON(),
-                                        multiple: true
-                                });
-                                selection.gallery = this.attachments.gallery;
-
-                                this.frame = wp.media({
-                                        frame:     'post',
-                                        state:     'gallery-edit',
-                                        title:     mceview.l10n.editGallery,
-                                        editing:   true,
-                                        multiple:  true,
-                                        selection: selection
-                                });
-
-                                // Create a single-use frame. If the frame is closed,
-                                // then detach it from the DOM and remove the reference.
-                                this.frame.on( 'close', function() {
-                                        if ( this.frame )
-                                                this.frame.detach();
-                                        delete this.frame;
-                                }, this );
-
-                                // Update the `shortcode` and `attachments`.
-                                this.frame.get('gallery-edit').on( 'update', function( selection ) {
-                                        var        view = mceview.get('gallery');
-
-                                        this.options.shortcode = view.gallery.shortcode( selection );
-                                        this.update();
-                                }, this );
-                        }
-                }
-        });
</del><span class="cx"> }(jQuery));
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpincludesjsshortcodejs"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/js/shortcode.js (22566 => 22567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/js/shortcode.js        2012-11-14 05:29:56 UTC (rev 22566)
+++ trunk/wp-includes/js/shortcode.js        2012-11-14 07:17:22 UTC (rev 22567)
</span><span class="lines">@@ -272,3 +272,71 @@
</span><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> }());
</span><ins>+
+// HTML utility functions
+// ----------------------
+//
+// Experimental. These functions may change or be removed in the future.
+(function(){
+        wp.html = _.extend( wp.html || {}, {
+                // ### Parse HTML attributes.
+                //
+                // Converts `content` to a set of parsed HTML attributes.
+                // Utilizes `wp.shortcode.attrs( content )`, which is a valid superset of
+                // the HTML attribute specification. Reformats the attributes into an
+                // object that contains the `attrs` with `key:value` mapping, and a record
+                // of the attributes that were entered using `empty` attribute syntax (i.e.
+                // with no value).
+                attrs: function( content ) {
+                        var result, attrs;
+
+                        // If `content` ends in a slash, strip it.
+                        if ( '/' === content[ content.length - 1 ] )
+                                content = content.slice( 0, -1 );
+
+                        result = wp.shortcode.attrs( content );
+                        attrs  = result.named;
+
+                        _.each( result.numeric, function( key ) {
+                                if ( /\s/.test( key ) )
+                                        return;
+
+                                attrs[ key ] = '';
+                        });
+
+                        return attrs;
+                },
+
+                // ### Convert an HTML-representation of an object to a string.
+                string: function( options ) {
+                        var text = '&lt;' + options.tag,
+                                content = options.content || '';
+
+                        _.each( options.attrs, function( value, attr ) {
+                                text += ' ' + attr;
+
+                                // Use empty attribute notation where possible.
+                                if ( '' === value )
+                                        return;
+
+                                // Convert boolean values to strings.
+                                if ( _.isBoolean( value ) )
+                                        value = value ? 'true' : 'false';
+
+                                text += '=&quot;' + value + '&quot;';
+                        });
+
+                        // Return the result if it is a self-closing tag.
+                        if ( options.single )
+                                return text + ' /&gt;';
+
+                        // Complete the opening tag.
+                        text += '&gt;';
+
+                        // If `content` is an object, recursively call this function.
+                        text += _.isObject( content ) ? wp.html.string( content ) : content;
+
+                        return text + '&lt;/' + options.tag + '&gt;';
+                }
+        });
+}());
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpincludesscriptloaderphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/script-loader.php (22566 => 22567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/script-loader.php        2012-11-14 05:29:56 UTC (rev 22566)
+++ trunk/wp-includes/script-loader.php        2012-11-14 07:17:22 UTC (rev 22567)
</span><span class="lines">@@ -298,7 +298,7 @@
</span><span class="cx">                 'type' =&gt; 'characters' == _x( 'words', 'word count: words or characters?' ) ? 'c' : 'w',
</span><span class="cx">         ) );
</span><span class="cx"> 
</span><del>-        $scripts-&gt;add( 'media-upload', &quot;/wp-admin/js/media-upload$suffix.js&quot;, array( 'thickbox', 'mce-view', 'media-views' ), false, 1 );
</del><ins>+        $scripts-&gt;add( 'media-upload', &quot;/wp-admin/js/media-upload$suffix.js&quot;, array( 'thickbox', 'shortcode', 'media-views' ), false, 1 );
</ins><span class="cx"> 
</span><span class="cx">         $scripts-&gt;add( 'hoverIntent', &quot;/wp-includes/js/hoverIntent$suffix.js&quot;, array('jquery'), 'r6', 1 );
</span><span class="cx"> 
</span><span class="lines">@@ -326,10 +326,6 @@
</span><span class="cx">         $scripts-&gt;add( 'media-views',  &quot;/wp-includes/js/media-views$suffix.js&quot;,  array( 'media-models', 'wp-plupload' ), false, 1 );
</span><span class="cx">         $scripts-&gt;add( 'shortcode', &quot;/wp-includes/js/shortcode$suffix.js&quot;, array( 'underscore' ), false, 1 );
</span><span class="cx">         $scripts-&gt;add( 'mce-view', &quot;/wp-includes/js/mce-view$suffix.js&quot;, array( 'shortcode', 'media-models' ), false, 1 );
</span><del>-        did_action( 'init' ) &amp;&amp; $scripts-&gt;localize( 'mce-view', '_wpMceViewL10n', array(
-                'contentWidth' =&gt; isset( $GLOBALS['content_width'] ) ? $GLOBALS['content_width'] : 800,
-                'editGallery'  =&gt; __( 'Edit Gallery' ),
-        ) );
</del><span class="cx"> 
</span><span class="cx">         if ( is_admin() ) {
</span><span class="cx">                 $scripts-&gt;add( 'ajaxcat', &quot;/wp-admin/js/cat$suffix.js&quot;, array( 'wp-lists' ) );
</span></span></pre>
</div>
</div>

</body>
</html>