Adds UI for media modal toolbars, buttons, and the selected item(s) status.

Currently uses actions for inserting media into a post as an example (hence the raw text). To test a workflow that supports multiple selection, run the following in your browser's JavaScript console:

	wp.media({ multiple: true });

see #21390, #21808.



git-svn-id: http://core.svn.wordpress.org/trunk@21769 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Daryl Koopersmith 2012-09-06 07:46:15 +00:00
parent fafbaa51e4
commit 43fc38330a
3 changed files with 351 additions and 5 deletions

View File

@ -53,6 +53,37 @@
overflow: auto; overflow: auto;
} }
/**
* Toolbar
*/
.media-toolbar {
position: relative;
z-index: 50;
height: 60px;
border-bottom: 1px solid #dfdfdf;
}
.media-toolbar-primary {
float: right;
}
.media-toolbar-secondary {
float: left;
}
.media-toolbar .media-button {
float: left;
margin-top: 19px;
}
.media-toolbar-primary .media-button {
margin-left: 10px;
}
.media-toolbar-secondary .media-button {
margin-right: 10px;
}
/** /**
* Workspace * Workspace
*/ */
@ -98,6 +129,7 @@
width: auto; width: auto;
right: 0; right: 0;
border-color: #83B4D8; border-color: #83B4D8;
box-shadow: 0 0 0 10px #fff;
} }
.existing-attachments { .existing-attachments {
@ -106,12 +138,56 @@
left: 200px; left: 200px;
right: 0; right: 0;
bottom: 0; bottom: 0;
margin: 0 20px;
}
.media-workspace .attachments,
.media-workspace .media-toolbar {
-webkit-transition-property: left, right, top, bottom, margin;
-moz-transition-property: left, right, top, bottom, margin;
-ms-transition-property: left, right, top, bottom, margin;
-o-transition-property: left, right, top, bottom, margin;
transition-property: left, right, top, bottom, margin;
-webkit-transition-duration: 0.2s;
-moz-transition-duration: 0.2s;
-ms-transition-duration: 0.2s;
-o-transition-duration: 0.2s;
transition-duration: 0.2s;
}
.media-workspace .attachments {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
height: auto;
width: auto;
}
.media-workspace.with-toolbar .attachments {
top: 61px;
}
.media-workspace .media-toolbar {
margin-top: -61px;
}
.media-workspace.with-toolbar .media-toolbar {
margin-top: 0;
}
.media-workspace .media-toolbar .add-to-gallery,
.media-workspace .media-toolbar .create-new-gallery {
display: none;
} }
/** /**
* Attachments * Attachments
*/ */
.attachments { .attachments {
position: relative;
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
@ -128,15 +204,15 @@
.attachments-header h3 { .attachments-header h3 {
float: left; float: left;
margin: 0; margin: 0;
padding: 0 0 0 10px; padding: 0;
line-height: 50px; line-height: 50px;
font-size: 18px; font-size: 18px;
font-weight: 200; font-weight: 200;
} }
.attachments-header input { .attachments-header input {
float: right; float: right;
margin-top: 10px; margin-top: 12px;
margin-right: 10px; line-height: 18px;
} }
.attachments ul { .attachments ul {
@ -146,7 +222,7 @@
right: 0; right: 0;
bottom: 0; bottom: 0;
overflow: auto; overflow: auto;
margin: 0 10px 20px; margin: 0 -10px 20px;
} }
/** /**
@ -171,6 +247,21 @@
border-color: #21759b; border-color: #21759b;
} }
.attachment.selected:after {
content: '\2713';
display: block;
height: 24px;
width: 24px;
position: absolute;
top: 0;
left: 0;
line-height: 24px;
font-size: 18px;
text-align: center;
color: #fff;
background: #21759b;
}
.attachment-thumbnail { .attachment-thumbnail {
position: absolute; position: absolute;
top: 0; top: 0;
@ -276,3 +367,67 @@
.uploading .upload-attachments .media-progress-bar { .uploading .upload-attachments .media-progress-bar {
display: block; display: block;
} }
/**
* Selection Preview
*/
.selection-preview {
position: relative;
height: 60px;
overflow: hidden;
}
.selected-img {
float: left;
position: relative;
margin-right: 14px;
}
.selection-preview img {
max-width: 40px;
max-height: 40px;
float: left;
margin-top: 6px;
margin-left: 1px;
border: 2px solid white;
box-shadow:
0 0 0 1px #ccc,
3px 3px 0 0 #fff,
3px 3px 0 1px #ccc,
6px 6px 0 0 #fff,
6px 6px 0 1px #ccc;
}
.selection-preview .selected-count-1 img {
margin-top: 8px;
box-shadow: 0 0 0 1px #ccc;
}
.selection-preview .selected-count-2 img {
margin-top: 7px;
box-shadow:
0 0 0 1px #ccc,
3px 3px 0 0 #fff,
3px 3px 0 1px #ccc;
}
.selection-preview .count {
position: absolute;
bottom: 0;
right: 0;
height: 16px;
min-width: 8px;
padding: 0 4px;
font-size: 12px;
text-align: center;
font-weight: bold;
color: #999;
background: #fff;
box-shadow: -1px -1px 2px -1px rgba( 0, 0, 0, 0.2 );
}
.selection-preview .clear-selection {
float: left;
line-height: 60px;
}

View File

@ -138,6 +138,102 @@
} }
}); });
/**
* wp.media.view.Toolbar
*/
media.view.Toolbar = Backbone.View.extend({
tagName: 'div',
className: 'media-toolbar',
initialize: function() {
this._views = {};
this.$primary = $('<div class="media-toolbar-primary" />').prependTo( this.$el );
this.$secondary = $('<div class="media-toolbar-secondary" />').prependTo( this.$el );
if ( this.options.items ) {
_.each( this.options.items, function( view, id ) {
this.add( id, view, { silent: true } );
}, this );
this.render();
}
},
render: function() {
var views = _.chain( this._views ).sortBy( function( view ) {
return view.options.priority || 10;
}).groupBy( function( view ) {
return ( view.options.priority || 10 ) > 0 ? 'primary' : 'secondary';
}).value();
// Make sure to detach the elements we want to reuse.
// Otherwise, `jQuery.html()` will unbind their events.
$( _.pluck( this._views, 'el' ) ).detach();
this.$primary.html( _.pluck( views.primary, 'el' ) );
this.$secondary.html( _.pluck( views.secondary, 'el' ) );
return this;
},
add: function( id, view, options ) {
if ( ! ( view instanceof Backbone.View ) ) {
view.classes = [ id ].concat( view.classes || [] );
view = new media.view.Button( view ).render();
}
this._views[ id ] = view;
if ( ! options || ! options.silent )
this.render();
return this;
},
remove: function( id, options ) {
delete this._views[ id ];
if ( ! options || ! options.silent )
this.render();
return this;
}
});
/**
* wp.media.view.Button
*/
media.view.Button = Backbone.View.extend({
tagName: 'a',
className: 'media-button',
attributes: { href: '#' },
events: {
'click': 'click'
},
initialize: function() {
_.defaults( this.options, {
style: 'secondary',
text: '',
classes: []
});
},
render: function() {
var classes = [ this.className ];
if ( this.options.style )
classes.push( 'button-' + this.options.style );
classes = classes.concat( this.options.classes );
this.el.className = classes.join(' ');
this.$el.text( this.options.text );
return this;
},
click: function( event ) {
event.preventDefault();
if ( this.options.click )
this.options.click.apply( this, arguments );
}
});
/** /**
* wp.media.view.Workspace * wp.media.view.Workspace
*/ */
@ -159,6 +255,12 @@
uploader: {} uploader: {}
}); });
this.$content = $('<div class="existing-attachments" />');
// If this supports multiple attachments, initialize the sample toolbar view.
if ( this.controller.get('multiple') )
this.initToolbarView();
this.attachmentsView = new media.view.Attachments({ this.attachmentsView = new media.view.Attachments({
controller: this.controller, controller: this.controller,
directions: 'Select stuff.', directions: 'Select stuff.',
@ -167,7 +269,6 @@
}) })
}); });
this.$content = $('<div class="existing-attachments" />');
this.$content.append( this.attachmentsView.$el ); this.$content.append( this.attachmentsView.$el );
// Track uploading attachments. // Track uploading attachments.
@ -242,6 +343,42 @@
file.attachment.destroy(); file.attachment.destroy();
} }
}, this.options.uploader ) ); }, this.options.uploader ) );
},
// Initializes the toolbar view. Currently uses defaults set for
// inserting media into a post. This should be pulled out into the
// appropriate workflow when the time comes, but is currently here
// to test multiple selections.
initToolbarView: function() {
this.toolbarView = new media.view.Toolbar({
items: {
'selection-preview': new media.view.SelectionPreview({
controller: this.controller,
collection: this.controller.selection,
priority: -40
}),
'insert-into-post': {
style: 'primary',
text: 'Insert into post',
priority: 40
},
'create-new-gallery': {
style: 'primary',
text: 'Create a new gallery',
priority: 30
},
'add-to-gallery': {
text: 'Add to gallery',
priority: 20
}
}
});
this.controller.selection.on( 'add remove', function() {
this.$el.toggleClass( 'with-toolbar', !! this.controller.selection.length );
}, this );
this.$content.append( this.toolbarView.$el );
} }
}); });
@ -426,4 +563,47 @@
this.$el.removeClass('selected'); this.$el.removeClass('selected');
} }
}); });
/**
* wp.media.view.SelectionPreview
*/
media.view.SelectionPreview = Backbone.View.extend({
tagName: 'div',
className: 'selection-preview',
template: media.template('media-selection-preview'),
events: {
'click .clear-selection': 'clear'
},
initialize: function() {
this.controller = this.options.controller;
this.collection.on( 'add change:url remove', this.render, this );
this.render();
},
render: function() {
var options = {},
first, sizes, amount;
// If nothing is selected, display nothing.
if ( ! this.collection.length ) {
this.$el.empty();
return this;
}
options.count = this.collection.length;
first = this.collection.first();
sizes = first.get('sizes');
options.thumbnail = ( sizes && sizes.thumbnail ) ? sizes.thumbnail.url : first.get('url');
this.$el.html( this.template( options ) );
return this;
},
clear: function( event ) {
event.preventDefault();
this.collection.clear();
}
});
}(jQuery)); }(jQuery));

View File

@ -1649,5 +1649,16 @@ function wp_print_media_templates( $attachment ) {
</div> </div>
<div class="describe"></div> <div class="describe"></div>
</script> </script>
<script type="text/html" id="tmpl-media-selection-preview">
<div class="selected-img selected-count-<%- count %>">
<% if ( thumbnail ) { %>
<img src="<%- thumbnail %>" />
<% } %>
<span class="count"><%- count %></span>
</div>
<a class="clear-selection" href="#"><?php _e('Clear selection'); ?></a>
</script>
<?php <?php
} }