<!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>[20179] trunk: Theme Customizer: First pass for upload controls, using background image as an example.</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/20179">20179</a></dd>
<dt>Author</dt> <dd>koopersmith</dd>
<dt>Date</dt> <dd>2012-03-15 04:14:05 +0000 (Thu, 15 Mar 2012)</dd>
</dl>

<h3>Log Message</h3>
<pre>Theme Customizer: First pass for upload controls, using background image as an example. Add a wrapper for Plupload that allows for custom upload UIs. see <a href="http://core.trac.wordpress.org/ticket/19910">#19910</a>.

wp.Uploader is a wrapper that provides a simple way to upload an attachment (using the wp_ajax_upload_attachment handler). It is intentionally decoupled from the UI. When an upload succeeds, it will receive the attachment information (id, url, meta, etc) as a JSON response. If the upload fails, the wrapper handles both WordPress and plupload errors through a single handler.

As todos, we should add drag classes for the uploader dropzone and account for the rough 100mb filesize limit in most browsers. The UI for the customizer upload controls could be improved as well.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpadminadminajaxphp">trunk/wp-admin/admin-ajax.php</a></li>
<li><a href="#trunkwpadminincludesajaxactionsphp">trunk/wp-admin/includes/ajax-actions.php</a></li>
<li><a href="#trunkwpincludesclasswpcustomizesettingphp">trunk/wp-includes/class-wp-customize-setting.php</a></li>
<li><a href="#trunkwpincludesclasswpcustomizephp">trunk/wp-includes/class-wp-customize.php</a></li>
<li><a href="#trunkwpincludesjscustomizecontrolsdevjs">trunk/wp-includes/js/customize-controls.dev.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>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkwpincludesjspluploadwppluploaddevjs">trunk/wp-includes/js/plupload/wp-plupload.dev.js</a></li>
<li><a href="#trunkwpincludesjspluploadwppluploadjs">trunk/wp-includes/js/plupload/wp-plupload.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpadminadminajaxphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/admin-ajax.php (20178 => 20179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/admin-ajax.php        2012-03-15 01:00:22 UTC (rev 20178)
+++ trunk/wp-admin/admin-ajax.php        2012-03-15 04:14:05 UTC (rev 20179)
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx">         'menu-locations-save', 'menu-quick-search', 'meta-box-order', 'get-permalink',
</span><span class="cx">         'sample-permalink', 'inline-save', 'inline-save-tax', 'find_posts', 'widgets-order',
</span><span class="cx">         'save-widget', 'set-post-thumbnail', 'date_format', 'time_format', 'wp-fullscreen-save-post',
</span><del>-        'wp-remove-post-lock', 'dismiss-wp-pointer',
</del><ins>+        'wp-remove-post-lock', 'dismiss-wp-pointer', 'upload-attachment',
</ins><span class="cx"> );
</span><span class="cx"> 
</span><span class="cx"> // Register core Ajax calls.
</span></span></pre></div>
<a id="trunkwpadminincludesajaxactionsphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/ajax-actions.php (20178 => 20179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/ajax-actions.php        2012-03-15 01:00:22 UTC (rev 20178)
+++ trunk/wp-admin/includes/ajax-actions.php        2012-03-15 04:14:05 UTC (rev 20179)
</span><span class="lines">@@ -1544,6 +1544,50 @@
</span><span class="cx">         wp_die();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+function wp_ajax_upload_attachment() {
+        check_ajax_referer( 'media-form' );
+
+        if ( ! current_user_can( 'upload_files' ) )
+                wp_die( -1 );
+
+        if ( isset( $_REQUEST['post_id'] ) ) {
+                $post_id = $_REQUEST['post_id'];
+                if ( ! current_user_can( 'edit_post', $post_id ) )
+                        wp_die( -1 );
+        } else {
+                $post_id = null;
+        }
+
+        $post_data = is_array( $_REQUEST['post_data'] ) ? $_REQUEST['post_data'] : array();
+
+        $attachment_id = media_handle_upload( 'async-upload', $post_id, $post_data );
+
+        if ( is_wp_error( $attachment_id ) ) {
+                echo json_encode( array(
+                        'type' =&gt; 'error',
+                        'data' =&gt; array(
+                                'message'  =&gt; $attachment_id-&gt;get_error_message(),
+                                'filename' =&gt; $_FILES['async-upload']['name'],
+                        ),
+                ) );
+                wp_die();
+        }
+
+        $post = get_post( $attachment_id );
+
+        echo json_encode( array(
+                'type' =&gt; 'success',
+                'data' =&gt; array(
+                        'id'       =&gt; $attachment_id,
+                        'title'    =&gt; esc_attr( $post-&gt;post_title ),
+                        'filename' =&gt; esc_html( basename( $post-&gt;guid ) ),
+                        'url'      =&gt; wp_get_attachment_url( $attachment_id ),
+                        'meta'     =&gt; wp_get_attachment_metadata( $attachment_id ),
+                ),
+        ) );
+        wp_die();
+}
+
</ins><span class="cx"> function wp_ajax_image_editor() {
</span><span class="cx">         $attachment_id = intval($_POST['postid']);
</span><span class="cx">         if ( empty($attachment_id) || !current_user_can('edit_post', $attachment_id) )
</span></span></pre></div>
<a id="trunkwpincludesclasswpcustomizesettingphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/class-wp-customize-setting.php (20178 => 20179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/class-wp-customize-setting.php        2012-03-15 01:00:22 UTC (rev 20178)
+++ trunk/wp-includes/class-wp-customize-setting.php        2012-03-15 04:14:05 UTC (rev 20179)
</span><span class="lines">@@ -70,6 +70,9 @@
</span><span class="cx">                                 wp_enqueue_script( 'farbtastic' );
</span><span class="cx">                                 wp_enqueue_style( 'farbtastic' );
</span><span class="cx">                                 break;
</span><ins>+                        case 'upload':
+                                wp_enqueue_script( 'wp-plupload' );
+                                break;
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -394,6 +397,15 @@
</span><span class="cx">                                 &lt;/select&gt;
</span><span class="cx">                                 &lt;?php
</span><span class="cx">                                 break;
</span><ins>+                        case 'upload':
+                                ?&gt;
+                                &lt;label&gt;&lt;?php echo esc_html( $this-&gt;label ); ?&gt;&lt;br/&gt;
+                                        &lt;input type=&quot;hidden&quot; value=&quot;&lt;?php echo esc_attr( $this-&gt;value() ); ?&gt;&quot; &lt;?php $this-&gt;name(); ?&gt; /&gt;
+                                        &lt;a href=&quot;#&quot; class=&quot;button-secondary upload&quot;&gt;&lt;?php _e( 'Upload' ); ?&gt;&lt;/a&gt;
+                                        &lt;a href=&quot;#&quot; class=&quot;remove&quot;&gt;&lt;?php _e( 'Remove' ); ?&gt;&lt;/a&gt;
+                                &lt;/label&gt;
+                                &lt;?php
+                                break;
</ins><span class="cx">                         default:
</span><span class="cx">                                 do_action( 'customize_render_control-' . $this-&gt;control, $this );
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkwpincludesclasswpcustomizephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/class-wp-customize.php (20178 => 20179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/class-wp-customize.php        2012-03-15 01:00:22 UTC (rev 20178)
+++ trunk/wp-includes/class-wp-customize.php        2012-03-15 04:14:05 UTC (rev 20179)
</span><span class="lines">@@ -523,9 +523,15 @@
</span><span class="cx">                         'section'           =&gt; 'background',
</span><span class="cx">                         'control'           =&gt; 'color',
</span><span class="cx">                         'default'           =&gt; defined( 'BACKGROUND_COLOR' ) ? BACKGROUND_COLOR : '',
</span><del>-                        'sanitize_callback' =&gt; 'sanitize_hexcolor'
</del><ins>+                        'sanitize_callback' =&gt; 'sanitize_hexcolor',
</ins><span class="cx">                 ) );
</span><span class="cx"> 
</span><ins>+                $this-&gt;add_setting( 'background_image', array(
+                        'label'             =&gt; 'Background Image',
+                        'section'           =&gt; 'background',
+                        'control'           =&gt; 'upload',
+                ) );
+
</ins><span class="cx">                 /* Nav Menus */
</span><span class="cx"> 
</span><span class="cx">                 $locations      = get_registered_nav_menus();
</span></span></pre></div>
<a id="trunkwpincludesjscustomizecontrolsdevjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/js/customize-controls.dev.js (20178 => 20179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/js/customize-controls.dev.js        2012-03-15 01:00:22 UTC (rev 20178)
+++ trunk/wp-includes/js/customize-controls.dev.js        2012-03-15 04:14:05 UTC (rev 20179)
</span><span class="lines">@@ -70,6 +70,26 @@
</span><span class="cx">                 }
</span><span class="cx">         });
</span><span class="cx"> 
</span><ins>+        api.UploadControl = api.Control.extend({
+                initialize: function( id, value, options ) {
+                        var control = this;
+
+                        api.Control.prototype.initialize.call( this, id, value, options );
+
+                        this.uploader = new wp.Uploader({
+                                browser: this.container.find('.upload'),
+                                success: function( attachment ) {
+                                        control.set( attachment.url );
+                                }
+                        });
+
+                        this.container.on( 'click', '.remove', function( event ) {
+                                control.set('');
+                                event.preventDefault();
+                        });
+                }
+        });
+
</ins><span class="cx">         // Change objects contained within the main customize object to Settings.
</span><span class="cx">         api.defaultConstructor = api.Setting;
</span><span class="cx"> 
</span><span class="lines">@@ -194,7 +214,8 @@
</span><span class="cx">          * ===================================================================== */
</span><span class="cx"> 
</span><span class="cx">         api.controls = {
</span><del>-                color: api.ColorControl
</del><ins>+                color:  api.ColorControl,
+                upload: api.UploadControl
</ins><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         $( function() {
</span><span class="lines">@@ -229,6 +250,9 @@
</span><span class="cx"> 
</span><span class="cx">                 // Background color uses postMessage by default
</span><span class="cx">                 api('background_color').method = 'postMessage';
</span><ins>+
+                // api('background_image').method = 'postMessage';
+                api('background_image').uploader.param( 'post_data', { context: 'custom-background' });
</ins><span class="cx">         });
</span><span class="cx"> 
</span><span class="cx"> })( wp, jQuery );
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpincludesjspluploadwppluploaddevjs"></a>
<div class="addfile"><h4>Added: trunk/wp-includes/js/plupload/wp-plupload.dev.js (0 => 20179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/js/plupload/wp-plupload.dev.js                                (rev 0)
+++ trunk/wp-includes/js/plupload/wp-plupload.dev.js        2012-03-15 04:14:05 UTC (rev 20179)
</span><span class="lines">@@ -0,0 +1,156 @@
</span><ins>+if ( typeof wp === 'undefined' )
+        var wp = {};
+
+(function( exports, $ ) {
+        /*
+         * An object that helps create a WordPress uploader using plupload.
+         *
+         * @param options - object - The options passed to the new plupload instance.
+         *    Requires the following parameters:
+         *    - container - The id of uploader container.
+         *    - browser   - The id of button to trigger the file select.
+         *    - dropzone  - The id of file drop target.
+         *    - plupload  - An object of parameters to pass to the plupload instance.
+         *    - params    - An object of parameters to pass to $_POST when uploading the file.
+         *                  Extends this.plupload.multipart_params under the hood.
+         *
+         * @param attributes - object - Attributes and methods for this specific instance.
+         */
+        var Uploader = function( options ) {
+                var self = this,
+                        elements = {
+                                container: 'container',
+                                browser:   'browse_button',
+                                dropzone:  'drop_element'
+                        },
+                        key;
+
+                this.plupload = $.extend( { multipart_params: {} }, wpPluploadDefaults );
+                this.container = document.body; // Set default container.
+
+                // Extend the instance with options
+                //
+                // Use deep extend to allow options.plupload to override individual
+                // default plupload keys.
+                $.extend( true, this, options );
+
+                // Proxy all methods so this always refers to the current instance.
+                for ( key in this ) {
+                        if ( $.isFunction( this[ key ] ) )
+                                this[ key ] = $.proxy( this[ key ], this );
+                }
+
+                // Ensure all elements are jQuery elements and have id attributes
+                // Then set the proper plupload arguments to the ids.
+                for ( key in elements ) {
+                        if ( ! this[ key ] )
+                                continue;
+
+                        this[ key ] = $( this[ key ] ).first();
+                        if ( ! this[ key ].prop('id') )
+                                this[ key ].prop( 'id', '__wp-uploader-id-' + Uploader.uuid++ );
+                        this.plupload[ elements[ key ] ] = this[ key ].prop('id');
+                }
+
+                this.uploader = new plupload.Uploader( this.plupload );
+                delete this.plupload;
+
+                // Set default params and remove this.params alias.
+                this.param( this.params || {} );
+                delete this.params;
+
+                this.uploader.bind( 'Init', this.init );
+
+                this.uploader.init();
+
+                this.uploader.bind( 'UploadProgress', this.progress );
+
+                this.uploader.bind( 'FileUploaded', function( up, file, response ) {
+                        response = JSON.parse( response.response );
+
+                        if ( ! response || ! response.type || ! response.data )
+                                return self.error( pluploadL10n.default_error );
+
+                        if ( 'error' === response.type )
+                                return self.error( response.data.message, response.data );
+
+                        if ( 'success' === response.type )
+                                return self.success( response.data );
+
+                });
+
+                this.uploader.bind( 'Error', function( up, error ) {
+                        var message = pluploadL10n.default_error,
+                                key;
+
+                        // Check for plupload errors.
+                        for ( key in Uploader.errorMap ) {
+                                if ( error.code === plupload[ key ] ) {
+                                        message = Uploader.errorMap[ key ];
+                                        break;
+                                }
+                        }
+
+                        self.error( message, error );
+                        up.refresh();
+                });
+
+                this.uploader.bind( 'FilesAdded', function( up, files ) {
+                        $.each( files, function() {
+                                self.added( this );
+                        });
+
+                        up.refresh();
+                        up.start();
+                });
+        };
+
+        Uploader.uuid = 0;
+
+        Uploader.errorMap = {
+                'FAILED':                 pluploadL10n.upload_failed,
+                'FILE_EXTENSION_ERROR':   pluploadL10n.invalid_filetype,
+                // 'FILE_SIZE_ERROR': '',
+                'IMAGE_FORMAT_ERROR':     pluploadL10n.not_an_image,
+                'IMAGE_MEMORY_ERROR':     pluploadL10n.image_memory_exceeded,
+                'IMAGE_DIMENSIONS_ERROR': pluploadL10n.image_dimensions_exceeded,
+                'GENERIC_ERROR':          pluploadL10n.upload_failed,
+                'IO_ERROR':               pluploadL10n.io_error,
+                'HTTP_ERROR':             pluploadL10n.http_error,
+                'SECURITY_ERROR':         pluploadL10n.security_error
+        };
+
+        $.extend( Uploader.prototype, {
+                /**
+                 * Acts as a shortcut to extending the uploader's multipart_params object.
+                 *
+                 * param( key )
+                 *    Returns the value of the key.
+                 *
+                 * param( key, value )
+                 *    Sets the value of a key.
+                 *
+                 * param( map )
+                 *    Sets values for a map of data.
+                 */
+                param: function( key, value ) {
+                        if ( arguments.length === 1 &amp;&amp; typeof key === 'string' )
+                                return this.uploader.settings.multipart_params[ key ];
+
+                        if ( arguments.length &gt; 1 ) {
+                                this.uploader.settings.multipart_params[ key ] = value;
+                        } else {
+                                $.extend( this.uploader.settings.multipart_params, key );
+                        }
+                },
+
+                init:     function() {},
+                error:    function() {},
+                success:  function() {},
+                added:    function() {},
+                progress: function() {},
+                complete: function() {}
+        });
+
+        exports.Uploader = Uploader;
+})( wp, jQuery );
</ins><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 (20178 => 20179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/media.php        2012-03-15 01:00:22 UTC (rev 20178)
+++ trunk/wp-includes/media.php        2012-03-15 04:14:05 UTC (rev 20179)
</span><span class="lines">@@ -1441,3 +1441,46 @@
</span><span class="cx"> 
</span><span class="cx">         return apply_filters( 'embed_googlevideo', '&lt;embed type=&quot;application/x-shockwave-flash&quot; src=&quot;http://video.google.com/googleplayer.swf?docid=' . esc_attr($matches[2]) . '&amp;amp;hl=en&amp;amp;fs=true&quot; style=&quot;width:' . esc_attr($width) . 'px;height:' . esc_attr($height) . 'px&quot; allowFullScreen=&quot;true&quot; allowScriptAccess=&quot;always&quot; /&gt;', $matches, $attr, $url, $rawattr );
</span><span class="cx"> }
</span><ins>+
+/**
+ * Prints default plupload arguments.
+ *
+ * @since 3.4.0
+ */
+function wp_plupload_default_settings() {
+        global $wp_scripts;
+
+        $max_upload_size = wp_max_upload_size();
+
+        $params = array(
+                'action' =&gt; 'upload-attachment',
+        );
+        $params = apply_filters( 'plupload_default_params', $params );
+
+        $params['_wpnonce'] = wp_create_nonce( 'media-form' );
+
+        $settings = array(
+                'runtimes'            =&gt; 'html5,silverlight,flash,html4',
+                'file_data_name'      =&gt; 'async-upload', // key passed to $_FILE.
+                'multiple_queues'     =&gt; true,
+                'max_file_size'       =&gt; $max_upload_size . 'b',
+                'url'                 =&gt; admin_url( 'admin-ajax.php' ),
+                'flash_swf_url'       =&gt; includes_url( 'js/plupload/plupload.flash.swf' ),
+                'silverlight_xap_url' =&gt; includes_url( 'js/plupload/plupload.silverlight.xap' ),
+                'filters'             =&gt; array( array( 'title' =&gt; __( 'Allowed Files' ), 'extensions' =&gt; '*') ),
+                'multipart'           =&gt; true,
+                'urlstream_upload'    =&gt; true,
+                'multipart_params'    =&gt; $params,
+        );
+
+        $settings = apply_filters( 'plupload_default_settings', $settings );
+
+        $script = 'var wpPluploadDefaults = ' . json_encode( $settings ) . ';';
+
+        $data = $wp_scripts-&gt;get_data( 'wp-plupload', 'data' );
+        if ( $data )
+                $script = &quot;$data\n$script&quot;;
+
+        $wp_scripts-&gt;add_data( 'wp-plupload', 'data', $script );
+}
+add_action( 'admin_init', 'wp_plupload_default_settings' );
</ins></span></pre></div>
<a id="trunkwpincludesscriptloaderphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/script-loader.php (20178 => 20179)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/script-loader.php        2012-03-15 01:00:22 UTC (rev 20178)
+++ trunk/wp-includes/script-loader.php        2012-03-15 04:14:05 UTC (rev 20179)
</span><span class="lines">@@ -228,6 +228,9 @@
</span><span class="cx">         $scripts-&gt;add( 'plupload-handlers', &quot;/wp-includes/js/plupload/handlers$suffix.js&quot;, array('plupload-all', 'jquery') );
</span><span class="cx">         $scripts-&gt;localize( 'plupload-handlers', 'pluploadL10n', $uploader_l10n );
</span><span class="cx"> 
</span><ins>+        $scripts-&gt;add( 'wp-plupload', &quot;/wp-includes/js/plupload/wp-plupload$suffix.js&quot;, array('plupload-all', 'jquery', 'json2') );
+        $scripts-&gt;localize( 'wp-plupload', 'pluploadL10n', $uploader_l10n );
+
</ins><span class="cx">         // keep 'swfupload' for back-compat.
</span><span class="cx">         $scripts-&gt;add( 'swfupload', '/wp-includes/js/swfupload/swfupload.js', array(), '2201-20110113');
</span><span class="cx">         $scripts-&gt;add( 'swfupload-swfobject', '/wp-includes/js/swfupload/plugins/swfupload.swfobject.js', array('swfupload', 'swfobject'), '2201a');
</span></span></pre>
</div>
</div>

</body>
</html>