diff --git a/wp-includes/css/media-views.css b/wp-includes/css/media-views.css index ed3dd91602..90ee1edb37 100644 --- a/wp-includes/css/media-views.css +++ b/wp-includes/css/media-views.css @@ -738,9 +738,14 @@ a.media-modal-close { } .media-uploader-status .media-progress-bar { + display: none; width: 100%; } +.uploading.media-uploader-status .media-progress-bar { + display: block; +} + .attachment-preview .media-progress-bar { position: absolute; top: 50%; @@ -750,17 +755,23 @@ a.media-modal-close { } .media-uploader-status { + position: relative; padding-bottom: 10px; border-bottom: 1px solid #dfdfdf; box-shadow: 0 1px 0 #fff; } .media-uploader-status .upload-details { + display: none; font-size: 12px; color: #666; text-shadow: 0 1px 0 #fff; } +.uploading.media-uploader-status .upload-details { + display: block; +} + .media-uploader-status .upload-detail-separator { padding: 0 4px; } @@ -769,6 +780,47 @@ a.media-modal-close { color: #464646; } +.media-uploader-status .upload-dismiss-errors, +.media-uploader-status .upload-errors { + display: none; +} + +.errors.media-uploader-status .upload-dismiss-errors, +.errors.media-uploader-status .upload-errors { + display: block; +} + +.media-uploader-status .upload-dismiss-errors { + position: absolute; + top: 0; + right: 0; + text-decoration: none; +} + +.media-uploader-status .upload-error { + margin: 8px 0 0 0; + padding: 8px; + border: 1px #c00 solid; + background: #ffebe8; + border-radius: 3px; +} + +.media-uploader-status .upload-error-label { + padding: 2px 4px; + margin-right: 8px; + font-weight: bold; + color: #fff; + background: #f00; + background: -webkit-linear-gradient( top, #e00, #a00 ); + border-radius: 3px; +} + +.media-uploader-status .upload-error-message { + display: block; + padding-top: 8px; + color: #b44; +} + .uploader-window { position: fixed; top: 0; diff --git a/wp-includes/js/media-views.js b/wp-includes/js/media-views.js index 798a143af9..a0f762f341 100644 --- a/wp-includes/js/media-views.js +++ b/wp-includes/js/media-views.js @@ -32,9 +32,11 @@ }()); // Makes it easier to bind events using transitions. - media.transition = function( selector ) { + media.transition = function( selector, sensitivity ) { var deferred = $.Deferred(); + sensitivity = sensitivity || 2000; + if ( $.support.transition ) { if ( ! (selector instanceof $) ) selector = $( selector ); @@ -42,6 +44,9 @@ // Resolve the deferred when the first element finishes animating. selector.first().one( $.support.transition.end, deferred.resolve ); + // Just in case the event doesn't trigger, fire a callback. + _.delay( deferred.resolve, sensitivity ); + // Otherwise, execute on the spot. } else { deferred.resolve(); @@ -1835,6 +1840,10 @@ className: 'media-uploader-status', template: media.template('uploader-status'), + events: { + 'click .upload-dismiss-errors': 'dismiss' + }, + initialize: function() { this.controller = this.options.controller; @@ -1844,6 +1853,8 @@ this.queue.on( 'add remove reset change:uploading', this.info, this ); this.errors = wp.Uploader.errors; + this.errors.on( 'add remove reset', this.visibility, this ); + this.errors.on( 'add', this.error, this ); }, dispose: function() { @@ -1854,6 +1865,7 @@ visibility: function() { this.$el.toggleClass( 'uploading', !! this.queue.length ); + this.$el.toggleClass( 'errors', !! this.errors.length ); this.$el.toggle( !! this.queue.length || !! this.errors.length ); }, @@ -1903,10 +1915,36 @@ this.$index.text( index + 1 ); this.$total.text( queue.length ); - this.$filename.html( active ? media.truncate( _.escape( active.get('filename') ), 24 ) : '' ); + this.$filename.html( active ? this.filename( active.get('filename') ) : '' ); + }, + + filename: function( filename ) { + return media.truncate( _.escape( filename ), 24 ); + }, + + error: function( error ) { + this.views.add( '.upload-errors', new media.view.UploaderStatusError({ + filename: this.filename( error.get('file').name ), + message: error.get('message') + }), { at: 0 }); + }, + + dismiss: function( event ) { + var errors = this.views.get('.upload-errors'); + + event.preventDefault(); + + if ( errors ) + _.invoke( errors, 'remove' ); + wp.Uploader.errors.reset(); } }); + media.view.UploaderStatusError = media.View.extend({ + className: 'upload-error', + template: media.template('uploader-status-error') + }); + /** * wp.media.view.Toolbar */ diff --git a/wp-includes/js/plupload/wp-plupload.js b/wp-includes/js/plupload/wp-plupload.js index 79522e59c5..9d2db5fb31 100644 --- a/wp-includes/js/plupload/wp-plupload.js +++ b/wp-includes/js/plupload/wp-plupload.js @@ -88,7 +88,7 @@ window.wp = window.wp || {}; file.attachment.destroy(); Uploader.errors.unshift({ - message: message, + message: message || pluploadL10n.default_error, data: data, file: file }); @@ -199,7 +199,7 @@ window.wp = window.wp || {}; if ( ! _.isObject( response ) || _.isUndefined( response.success ) ) return error( pluploadL10n.default_error, null, file ); else if ( ! response.success ) - return error( response.data.message, response.data, file ); + return error( response.data && response.data.message, response.data, file ); _.each(['file','loaded','size','percent'], function( key ) { file.attachment.unset( key ); diff --git a/wp-includes/media.php b/wp-includes/media.php index e96bcea0b0..545aee7612 100644 --- a/wp-includes/media.php +++ b/wp-includes/media.php @@ -1503,6 +1503,8 @@ function wp_print_media_templates( $attachment ) { + +