Media grid, round 2. Expect much more to come.
* Instead of a sidebar for details, utilize a modal. The modal experience allows for a larger preview, editing images, audio/video previews, and previous/next navigation, like the theme browser. Think of it as an attachment browser. * Show some details in the grid view to more easily distinguish items. props ericlewis, wonderboymusic, JerrySarcastic. see #24716. git-svn-id: https://develop.svn.wordpress.org/trunk@28993 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
9c314d1d00
commit
e14d866665
@ -26,14 +26,6 @@ if ( 'grid' === $mode ) {
|
||||
wp_enqueue_script( 'media' );
|
||||
|
||||
require_once( ABSPATH . 'wp-admin/admin-header.php' );
|
||||
?><div class="view-switch media-grid-view-switch">
|
||||
<a href="<?php echo esc_url( add_query_arg( 'mode', 'list', $_SERVER['REQUEST_URI'] ) ) ?>" class="view-list">
|
||||
<img id="view-switch-list" src="<?php echo includes_url( 'images/blank.gif' ) ?>" width="20" height="20" title="List View" alt="List View"/>
|
||||
</a>
|
||||
<a href="<?php echo esc_url( add_query_arg( 'mode', 'grid', $_SERVER['REQUEST_URI'] ) ) ?>" class="view-grid current">
|
||||
<img id="view-switch-excerpt" src="<?php echo includes_url( 'images/blank.gif' ) ?>" width="20" height="20" title="Grid View" alt="Grid View"/>
|
||||
</a>
|
||||
</div><?php
|
||||
include( ABSPATH . 'wp-admin/admin-footer.php' );
|
||||
exit;
|
||||
}
|
||||
|
@ -750,6 +750,30 @@
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.attachment-preview.type-audio .thumbnail,
|
||||
.attachment-preview.type-video .thumbnail {
|
||||
z-index: 1;
|
||||
margin: 5%;
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
}
|
||||
|
||||
.media-frame-content .attachment-preview.type-audio .icon,
|
||||
.media-frame-content .attachment-preview.type-video .icon {
|
||||
z-index: 2;
|
||||
background: #f1f1f1;
|
||||
position: relative;
|
||||
padding: 0;
|
||||
top: 15%;
|
||||
left: auto;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
.attachment-preview.type-audio .filename,
|
||||
.attachment-preview.type-video .filename {
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.attachment-preview .thumbnail:after {
|
||||
content: '';
|
||||
display: block;
|
||||
@ -909,6 +933,22 @@
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.attachment .data-fields {
|
||||
margin: 5px 0 0;
|
||||
}
|
||||
|
||||
.attachment .data-field {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
line-height: 19px;
|
||||
height: 19px;
|
||||
text-align: left;
|
||||
width: 90%;
|
||||
margin: 0 5%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attachments Browser
|
||||
*/
|
||||
@ -924,6 +964,10 @@
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.attachments-browser.hide-sidebar .media-toolbar {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.attachments-browser .media-toolbar-primary > .media-button,
|
||||
.attachments-browser .media-toolbar-primary > .media-button-group,
|
||||
.attachments-browser .media-toolbar-secondary > .media-button,
|
||||
@ -942,6 +986,92 @@
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.inline-toolbar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: none;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.inline-toolbar .remove {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.active-video .inline-toolbar .remove {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.attachment:hover .inline-toolbar {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.inline-toolbar div,
|
||||
.inline-toolbar .inline-media-control {
|
||||
display: inline-block;
|
||||
margin-top: 4px;
|
||||
margin-left: 4px;
|
||||
padding: 2px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.5);
|
||||
background-color: #000;
|
||||
background-color: rgba(0,0,0,0.9);
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.ie8 .inline-toolbar div,
|
||||
.ie7 .inline-toolbar div {
|
||||
display: inline;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.inline-media-control span {
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 2px;
|
||||
background: url(/wp-includes/js/mediaelement/controls.png) 0 0 no-repeat;
|
||||
}
|
||||
|
||||
.inline-media-control.active span {
|
||||
margin: 2px;
|
||||
background-position: 0 -16px;
|
||||
}
|
||||
|
||||
.inline-media-control.paused span {
|
||||
margin: 2px;
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
audio#inline-media-node {
|
||||
display: none;
|
||||
}
|
||||
|
||||
video#inline-media-node {
|
||||
position: relative;
|
||||
z-index: 5;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.inline-video-wrap {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
background: #000;
|
||||
padding: 10px 0 5px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.attachments-browser.hide-sidebar .attachments {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.attachments-browser .instructions {
|
||||
display: inline-block;
|
||||
margin-top: 16px;
|
||||
@ -2388,11 +2518,11 @@
|
||||
line-height: 29px;
|
||||
}
|
||||
|
||||
.media-grid-view-switch {
|
||||
position: fixed;
|
||||
right: 10px;
|
||||
top: 44px;
|
||||
z-index: 300;
|
||||
.media-grid-view .view-switch {
|
||||
display: inline-block;
|
||||
float: none;
|
||||
margin-top: 13px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2427,7 +2557,221 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copied styles from the Add theme toolbar.
|
||||
*
|
||||
* This should be OOCSS'd so both use a shared selector.
|
||||
*/
|
||||
.media-grid-view .media-toolbar {
|
||||
background: #fff;
|
||||
-webkit-box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
|
||||
box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
color: #555;
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
padding: 0 20px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/**
|
||||
* The left and right buttons are copied from the expanded theme details modal.
|
||||
*
|
||||
* This should be OOCSS'd so both use a shared selector.
|
||||
*/
|
||||
.edit-attachment-frame .edit-media-header .left,
|
||||
.edit-attachment-frame .edit-media-header .right {
|
||||
cursor: pointer;
|
||||
color: #777;
|
||||
background-color: transparent;
|
||||
height: 48px;
|
||||
width: 54px;
|
||||
float: left;
|
||||
text-align: center;
|
||||
border: 0;
|
||||
border-right: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .edit-media-header .right:before,
|
||||
.edit-attachment-frame .edit-media-header .left:before {
|
||||
font: normal 20px/50px 'dashicons' !important;
|
||||
display: inline;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
|
||||
.edit-attachment-frame .edit-media-header .left:before {
|
||||
content: '\f340';
|
||||
}
|
||||
|
||||
.edit-attachment-frame .edit-media-header .right:before {
|
||||
content: '\f344';
|
||||
}
|
||||
|
||||
.edit-attachment-frame .edit-media-header .left.disabled,
|
||||
.edit-attachment-frame .edit-media-header .right.disabled,
|
||||
.edit-attachment-frame .edit-media-header .left.disabled:hover,
|
||||
.edit-attachment-frame .edit-media-header .right.disabled:hover {
|
||||
color: #ccc;
|
||||
background: inherit;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .edit-media-header .close:hover,
|
||||
.edit-attachment-frame .edit-media-header .right:hover,
|
||||
.edit-attachment-frame .edit-media-header .left:hover,
|
||||
.edit-attachment-frame .edit-media-header .close:focus,
|
||||
.edit-attachment-frame .edit-media-header .right:focus,
|
||||
.edit-attachment-frame .edit-media-header .left:focus {
|
||||
background: #0074a2;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .media-frame-content,
|
||||
.edit-attachment-frame .media-frame-router {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* Hiding this for the moment instead of removing it from the template. */
|
||||
.edit-attachment-frame h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-details {
|
||||
position: absolute;
|
||||
overflow: auto;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-info {
|
||||
border-bottom: 0;
|
||||
border-right: 1px solid #ddd;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin-bottom: 0;
|
||||
padding: 2% 4%;
|
||||
right: 50%;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-info .thumbnail {
|
||||
max-width: none;
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-info .thumbnail-image img {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-info .thumbnail-image:after {
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-info .thumbnail img {
|
||||
max-width: none;
|
||||
max-height: 50%;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-info .details {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .wp-media-wrapper {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-fields {
|
||||
bottom: 0;
|
||||
padding: 2% 4%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-fields .setting {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 100%;
|
||||
margin: 1px 0;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-fields .setting label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-fields .setting .link-to-custom {
|
||||
margin: 3px 0;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-fields .setting .name {
|
||||
min-width: 30%;
|
||||
margin-right: 4%;
|
||||
font-size: 12px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-fields .setting select {
|
||||
max-width: 65%;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-fields .setting input[type="checkbox"],
|
||||
.edit-attachment-frame .attachment-fields .field input[type="checkbox"] {
|
||||
width: 16px;
|
||||
float: none;
|
||||
margin: 8px 3px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-fields .setting span {
|
||||
float: left;
|
||||
min-height: 22px;
|
||||
padding-top: 8px;
|
||||
line-height: 16px;
|
||||
font-weight: normal;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-fields .setting input[type="text"],
|
||||
.edit-attachment-frame .attachment-fields .setting input[type="password"],
|
||||
.edit-attachment-frame .attachment-fields .setting input[type="number"],
|
||||
.edit-attachment-frame .attachment-fields .setting input[type="search"],
|
||||
.edit-attachment-frame .attachment-fields .setting input[type="email"],
|
||||
.edit-attachment-frame .attachment-fields .setting input[type="url"],
|
||||
.edit-attachment-frame .attachment-fields .setting textarea,
|
||||
.edit-attachment-frame .attachment-fields .setting .value {
|
||||
margin: 1px;
|
||||
width: 65%;
|
||||
float: right;
|
||||
padding: 6px 8px;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-fields .setting textarea {
|
||||
height: 62px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.edit-attachment-frame .attachment-fields select {
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.media-grid-view.hide-router .media-frame-title {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.media-grid-view .media-frame-content {
|
||||
background-color: transparent;
|
||||
bottom: 40px;
|
||||
}
|
||||
@media screen and (max-width: 782px) {
|
||||
|
@ -26,6 +26,17 @@
|
||||
}
|
||||
},
|
||||
|
||||
removeAllPlayers: function() {
|
||||
var p;
|
||||
|
||||
if ( window.mejs && window.mejs.players ) {
|
||||
for ( p in window.mejs.players ) {
|
||||
window.mejs.players[p].pause();
|
||||
this.removePlayer( window.mejs.players[p] );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Pauses the current object's instances of MediaElementPlayer
|
||||
*/
|
||||
|
@ -9,6 +9,96 @@
|
||||
delete l10n.settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* A state for editing (cropping, etc.) an image.
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.media.controller.State
|
||||
* @augments Backbone.Model
|
||||
*/
|
||||
media.controller.EditImageNoFrame = media.controller._State.extend({
|
||||
defaults: {
|
||||
id: 'edit-attachment',
|
||||
title: l10n.editImage,
|
||||
// Region mode defaults.
|
||||
menu: false,
|
||||
router: 'edit-metadata',
|
||||
content: 'edit-metadata',
|
||||
toolbar: 'toolbar',
|
||||
|
||||
url: ''
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
media.controller._State.prototype.initialize.apply( this, arguments );
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
this.listenTo( this.frame, 'toolbar:render:edit-image', this.toolbar );
|
||||
},
|
||||
|
||||
_postActivate: function() {
|
||||
this._content();
|
||||
this._router();
|
||||
},
|
||||
|
||||
deactivate: function() {
|
||||
this.stopListening( this.frame );
|
||||
},
|
||||
|
||||
toolbar: function() {
|
||||
var frame = this.frame,
|
||||
lastState = frame.lastState(),
|
||||
previous = lastState && lastState.id;
|
||||
|
||||
frame.toolbar.set( new media.view.Toolbar({
|
||||
controller: frame,
|
||||
items: {
|
||||
back: {
|
||||
style: 'primary',
|
||||
text: l10n.back,
|
||||
priority: 20,
|
||||
click: function() {
|
||||
if ( previous ) {
|
||||
frame.setState( previous );
|
||||
} else {
|
||||
frame.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}) );
|
||||
},
|
||||
|
||||
/**
|
||||
* @access private
|
||||
*/
|
||||
_router: function() {
|
||||
var router = this.frame.router,
|
||||
mode = this.get('router'),
|
||||
view;
|
||||
|
||||
this.frame.$el.toggleClass( 'hide-router', ! mode );
|
||||
if ( ! mode ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.frame.router.render( mode );
|
||||
|
||||
view = router.get();
|
||||
if ( view && view.select ) {
|
||||
view.select( this.frame.content.mode() );
|
||||
}
|
||||
},
|
||||
|
||||
_content: function() {
|
||||
var mode = this.get( 'content' );
|
||||
if ( mode ) {
|
||||
this.frame[ 'content' ].render( mode );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* wp.media.view.MediaFrame.Manage
|
||||
*
|
||||
@ -36,7 +126,8 @@
|
||||
library: {},
|
||||
multiple: false,
|
||||
state: 'library',
|
||||
uploader: true
|
||||
uploader: true,
|
||||
mode: [ 'grid', 'edit' ]
|
||||
});
|
||||
|
||||
// Ensure core and media grid view UI is enabled.
|
||||
@ -111,15 +202,56 @@
|
||||
router: false,
|
||||
content: 'browse',
|
||||
filterable: 'mime-types'
|
||||
}),
|
||||
|
||||
new media.controller.EditImage( { model: options.editImage } )
|
||||
})
|
||||
]);
|
||||
},
|
||||
|
||||
bindHandlers: function() {
|
||||
this.on( 'content:create:browse', this.browseContent, this );
|
||||
this.on( 'content:render:edit-image', this.editImageContent, this );
|
||||
|
||||
// Handle a frame-level event for editing an attachment.
|
||||
this.on( 'edit:attachment', this.editAttachment, this );
|
||||
this.on( 'edit:attachment:next', this.editNextAttachment, this );
|
||||
this.on( 'edit:attachment:previous', this.editPreviousAttachment, this );
|
||||
},
|
||||
|
||||
editPreviousAttachment: function( currentModel ) {
|
||||
var library = this.state().get('library'),
|
||||
currentModelIndex = library.indexOf( currentModel );
|
||||
this.trigger( 'edit:attachment', library.at( currentModelIndex - 1 ) );
|
||||
},
|
||||
|
||||
editNextAttachment: function( currentModel ) {
|
||||
var library = this.state().get('library'),
|
||||
currentModelIndex = library.indexOf( currentModel );
|
||||
this.trigger( 'edit:attachment', library.at( currentModelIndex + 1 ) );
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the Edit Attachment modal.
|
||||
*/
|
||||
editAttachment: function( model ) {
|
||||
var library = this.state().get('library'), hasPrevious, hasNext;
|
||||
if ( library.indexOf( model ) > 0 ) {
|
||||
hasPrevious = true;
|
||||
}
|
||||
else {
|
||||
hasPrevious = false;
|
||||
}
|
||||
if ( library.indexOf( model ) < library.length - 1 ) {
|
||||
hasNext = true;
|
||||
}
|
||||
else {
|
||||
hasNext = false;
|
||||
}
|
||||
|
||||
new media.view.Frame.EditAttachment({
|
||||
hasPrevious: hasPrevious,
|
||||
hasNext: hasNext,
|
||||
model: model,
|
||||
gridController: this
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@ -143,6 +275,7 @@
|
||||
display: state.get('displaySettings'),
|
||||
dragInfo: state.get('dragInfo'),
|
||||
bulkEdit: true,
|
||||
sidebar: false,
|
||||
|
||||
suggestedWidth: state.get('suggestedWidth'),
|
||||
suggestedHeight: state.get('suggestedHeight'),
|
||||
@ -163,4 +296,193 @@
|
||||
}
|
||||
});
|
||||
|
||||
media.view.Attachment.Details.TwoColumn = media.view.Attachment.Details.extend({
|
||||
template: wp.template( 'attachment-details-two-column' ),
|
||||
|
||||
initialize: function() {
|
||||
this.$el.attr('aria-label', this.model.attributes.title).attr('aria-checked', false);
|
||||
this.model.on( 'change:sizes change:uploading', this.render, this );
|
||||
this.model.on( 'change:title', this._syncTitle, this );
|
||||
this.model.on( 'change:caption', this._syncCaption, this );
|
||||
this.model.on( 'change:percent', this.progress, this );
|
||||
|
||||
// Update the selection.
|
||||
this.model.on( 'add', this.select, this );
|
||||
this.model.on( 'remove', this.deselect, this );
|
||||
},
|
||||
|
||||
render: function() {
|
||||
media.view.Attachment.Details.prototype.render.apply( this, arguments );
|
||||
|
||||
media.mixin.removeAllPlayers();
|
||||
$( 'audio, video', this.$el ).each( function (i, elem) {
|
||||
var el = media.view.MediaDetails.prepareSrc( elem );
|
||||
new MediaElementPlayer( el, media.mixin.mejsSettings );
|
||||
} );
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* A frame for editing the details of a specific media item.
|
||||
*
|
||||
* Opens in a modal by default.
|
||||
*
|
||||
* Requires an attachment model to be passed in the options hash under `model`.
|
||||
*/
|
||||
media.view.Frame.EditAttachment = media.view.Frame.extend({
|
||||
|
||||
className: 'edit-attachment-frame',
|
||||
template: media.template( 'edit-attachment-frame' ),
|
||||
regions: [ 'router', 'content' ],
|
||||
|
||||
events: {
|
||||
'click': 'collapse',
|
||||
'click .delete-media-item': 'deleteMediaItem',
|
||||
'click .left': 'previousMediaItem',
|
||||
'click .right': 'nextMediaItem'
|
||||
},
|
||||
|
||||
initialize: function( options ) {
|
||||
var self = this;
|
||||
media.view.Frame.prototype.initialize.apply( this, arguments );
|
||||
|
||||
_.defaults( this.options, {
|
||||
modal: true,
|
||||
state: 'edit-attachment'
|
||||
});
|
||||
|
||||
this.createStates();
|
||||
|
||||
this.on( 'content:render:edit-metadata', this.editMetadataContent, this );
|
||||
this.on( 'content:render:edit-image', this.editImageContentUgh, this );
|
||||
|
||||
// Only need a tab to Edit Image for images.
|
||||
if ( this.model.get( 'type' ) === 'image' ) {
|
||||
this.on( 'router:create', this.createRouter, this );
|
||||
this.on( 'router:render', this.browseRouter, this );
|
||||
}
|
||||
|
||||
// Initialize modal container view.
|
||||
if ( this.options.modal ) {
|
||||
this.modal = new media.view.Modal({
|
||||
controller: this,
|
||||
title: this.options.title
|
||||
});
|
||||
|
||||
// Completely destroy the modal DOM element when closing it.
|
||||
this.modal.close = function() {
|
||||
self.modal.remove();
|
||||
};
|
||||
|
||||
this.modal.content( this );
|
||||
this.modal.open();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add the default states to the frame.
|
||||
*/
|
||||
createStates: function() {
|
||||
this.states.add([
|
||||
new media.controller.EditImageNoFrame( { model: this.model } )
|
||||
]);
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {wp.media.view.MediaFrame} Returns itself to allow chaining
|
||||
*/
|
||||
render: function() {
|
||||
// Activate the default state if no active state exists.
|
||||
if ( ! this.state() && this.options.state ) {
|
||||
this.setState( this.options.state );
|
||||
}
|
||||
/**
|
||||
* call 'render' directly on the parent class
|
||||
*/
|
||||
return media.view.Frame.prototype.render.apply( this, arguments );
|
||||
},
|
||||
|
||||
/**
|
||||
* Content region rendering callback for the `edit-metadata` mode.
|
||||
*/
|
||||
editMetadataContent: function() {
|
||||
var view = new media.view.Attachment.Details.TwoColumn({
|
||||
controller: this,
|
||||
model: this.model
|
||||
});
|
||||
this.content.set( view );
|
||||
},
|
||||
|
||||
/**
|
||||
* For some reason the view doesn't exist in the DOM yet, don't have the
|
||||
* patience to track this down right now.
|
||||
*/
|
||||
editImageContentUgh: function() {
|
||||
_.defer( _.bind( this.editImageContent, this ) );
|
||||
},
|
||||
|
||||
/**
|
||||
* Render the EditImage view into the frame's content region.
|
||||
*/
|
||||
editImageContent: function() {
|
||||
var view = new media.view.EditImage( { model: this.model, controller: this } ).render();
|
||||
|
||||
this.content.set( view );
|
||||
|
||||
// after creating the wrapper view, load the actual editor via an ajax call
|
||||
view.loadEditor();
|
||||
},
|
||||
|
||||
/**
|
||||
* Create the router view.
|
||||
*
|
||||
* @param {Object} router
|
||||
* @this wp.media.controller.Region
|
||||
*/
|
||||
createRouter: function( router ) {
|
||||
router.view = new media.view.Router({
|
||||
controller: this
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Router rendering callback.
|
||||
*
|
||||
* @param media.view.Router view Instantiated in this.createRouter()
|
||||
*/
|
||||
browseRouter: function( view ) {
|
||||
view.set({
|
||||
'edit-metadata': {
|
||||
text: 'Edit Metadata',
|
||||
priority: 20
|
||||
},
|
||||
'edit-image': {
|
||||
text: 'Edit Image',
|
||||
priority: 40
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Click handler to switch to the previous media item.
|
||||
*/
|
||||
previousMediaItem: function() {
|
||||
if ( ! this.options.hasPrevious )
|
||||
return;
|
||||
this.modal.close();
|
||||
this.options.gridController.trigger( 'edit:attachment:previous', this.model );
|
||||
},
|
||||
|
||||
/**
|
||||
* Click handler to switch to the next media item.
|
||||
*/
|
||||
nextMediaItem: function() {
|
||||
if ( ! this.options.hasNext )
|
||||
return;
|
||||
this.modal.close();
|
||||
this.options.gridController.trigger( 'edit:attachment:next', this.model );
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}(jQuery, _, Backbone, wp));
|
@ -337,16 +337,11 @@
|
||||
});
|
||||
|
||||
/**
|
||||
* wp.media.controller.State
|
||||
*
|
||||
* A state is a step in a workflow that when set will trigger the controllers
|
||||
* for the regions to be updated as specified in the frame. This is the base
|
||||
* class that the various states used in wp.media extend.
|
||||
*
|
||||
* @constructor
|
||||
* @augments Backbone.Model
|
||||
* A more abstracted state, because media.controller.State expects
|
||||
* specific regions (menu, title, etc.) to exist on the frame, which do not
|
||||
* exist in media.view.Frame.EditAttachment.
|
||||
*/
|
||||
media.controller.State = Backbone.Model.extend({
|
||||
media.controller._State = Backbone.Model.extend({
|
||||
constructor: function() {
|
||||
this.on( 'activate', this._preActivate, this );
|
||||
this.on( 'activate', this.activate, this );
|
||||
@ -354,13 +349,11 @@
|
||||
this.on( 'deactivate', this._deactivate, this );
|
||||
this.on( 'deactivate', this.deactivate, this );
|
||||
this.on( 'reset', this.reset, this );
|
||||
this.on( 'ready', this._ready, this );
|
||||
this.on( 'ready', this.ready, this );
|
||||
/**
|
||||
* Call parent constructor with passed arguments
|
||||
*/
|
||||
Backbone.Model.apply( this, arguments );
|
||||
this.on( 'change:menu', this._updateMenu, this );
|
||||
},
|
||||
|
||||
/**
|
||||
@ -382,15 +375,55 @@
|
||||
/**
|
||||
* @access private
|
||||
*/
|
||||
_ready: function() {
|
||||
this._updateMenu();
|
||||
_preActivate: function() {
|
||||
this.active = true;
|
||||
},
|
||||
/**
|
||||
* @access private
|
||||
*/
|
||||
_preActivate: function() {
|
||||
this.active = true;
|
||||
_postActivate: function() {},
|
||||
/**
|
||||
* @access private
|
||||
*/
|
||||
_deactivate: function() {
|
||||
this.active = false;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* wp.media.controller.State
|
||||
*
|
||||
* A state is a step in a workflow that when set will trigger the controllers
|
||||
* for the regions to be updated as specified in the frame. This is the base
|
||||
* class that the various states used in wp.media extend.
|
||||
*
|
||||
* @constructor
|
||||
* @augments Backbone.Model
|
||||
*/
|
||||
media.controller.State = media.controller._State.extend({
|
||||
constructor: function() {
|
||||
this.on( 'activate', this._preActivate, this );
|
||||
this.on( 'activate', this.activate, this );
|
||||
this.on( 'activate', this._postActivate, this );
|
||||
this.on( 'deactivate', this._deactivate, this );
|
||||
this.on( 'deactivate', this.deactivate, this );
|
||||
this.on( 'reset', this.reset, this );
|
||||
this.on( 'ready', this._ready, this );
|
||||
this.on( 'ready', this.ready, this );
|
||||
/**
|
||||
* Call parent constructor with passed arguments
|
||||
*/
|
||||
Backbone.Model.apply( this, arguments );
|
||||
this.on( 'change:menu', this._updateMenu, this );
|
||||
},
|
||||
|
||||
/**
|
||||
* @access private
|
||||
*/
|
||||
_ready: function() {
|
||||
this._updateMenu();
|
||||
},
|
||||
|
||||
/**
|
||||
* @access private
|
||||
*/
|
||||
@ -1758,7 +1791,8 @@
|
||||
_.defaults( this.options, {
|
||||
title: '',
|
||||
modal: true,
|
||||
uploader: true
|
||||
uploader: true,
|
||||
mode: ['select']
|
||||
});
|
||||
|
||||
// Ensure core UI is enabled.
|
||||
@ -4530,7 +4564,7 @@
|
||||
var selection = this.options.selection;
|
||||
|
||||
this.$el.attr('aria-label', this.model.attributes.title).attr('aria-checked', false);
|
||||
this.model.on( 'change:sizes change:uploading', this.render, this );
|
||||
this.model.on( 'change', this.render, this );
|
||||
this.model.on( 'change:title', this._syncTitle, this );
|
||||
this.model.on( 'change:caption', this._syncCaption, this );
|
||||
this.model.on( 'change:percent', this.progress, this );
|
||||
@ -4583,7 +4617,7 @@
|
||||
compat: false,
|
||||
alt: '',
|
||||
description: ''
|
||||
});
|
||||
}, this.options );
|
||||
|
||||
options.buttons = this.buttons;
|
||||
options.describe = this.controller.state().get('describe');
|
||||
@ -4633,11 +4667,17 @@
|
||||
*/
|
||||
toggleSelectionHandler: function( event ) {
|
||||
var method;
|
||||
|
||||
// Catch enter and space events
|
||||
if ( 'keydown' === event.type && 13 !== event.keyCode && 32 !== event.keyCode ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// In the grid view, bubble up an edit:attachment event to the controller.
|
||||
if ( _.contains( this.controller.options.mode, 'grid' ) ) {
|
||||
this.controller.trigger( 'edit:attachment', this.model );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( event.shiftKey ) {
|
||||
method = 'between';
|
||||
} else if ( event.ctrlKey || event.metaKey ) {
|
||||
@ -5171,7 +5211,8 @@
|
||||
controller: this.controller,
|
||||
model: attachment,
|
||||
collection: this.collection,
|
||||
selection: this.options.selection
|
||||
selection: this.options.selection,
|
||||
showAttachmentFields: this.options.showAttachmentFields
|
||||
});
|
||||
|
||||
return this._viewsByCid[ attachment.cid ] = view;
|
||||
@ -5468,7 +5509,6 @@
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* wp.media.view.AttachmentsBrowser
|
||||
*
|
||||
@ -5486,13 +5526,18 @@
|
||||
filters: false,
|
||||
search: true,
|
||||
display: false,
|
||||
|
||||
sidebar: true,
|
||||
showAttachmentFields: getUserSetting( 'showAttachmentFields', [ 'title', 'uploadedTo', 'dateFormatted', 'mime' ] ),
|
||||
AttachmentView: media.view.Attachment.Library
|
||||
});
|
||||
|
||||
this.createToolbar();
|
||||
this.updateContent();
|
||||
if ( this.options.sidebar ) {
|
||||
this.createSidebar();
|
||||
} else {
|
||||
this.$el.addClass( 'hide-sidebar' );
|
||||
}
|
||||
|
||||
this.collection.on( 'add remove reset', this.updateContent, this );
|
||||
},
|
||||
@ -5517,6 +5562,20 @@
|
||||
|
||||
this.views.add( this.toolbar );
|
||||
|
||||
// Feels odd to bring the global media library switcher into the Attachment
|
||||
// browser view. Is this a use case for doAction( 'add:toolbar-items:attachments-browser', this.toolbar );
|
||||
// which the controller can tap into and add this view?
|
||||
if ( _.contains( this.controller.options.mode, 'grid' ) ) {
|
||||
var libraryViewSwitcherConstructor = media.View.extend({
|
||||
className: 'view-switch media-grid-view-switch',
|
||||
template: media.template( 'media-library-view-switcher')
|
||||
});
|
||||
this.toolbar.set( 'libraryViewSwitcher', new libraryViewSwitcherConstructor({
|
||||
controller: this.controller,
|
||||
priority: -90
|
||||
}).render() );
|
||||
}
|
||||
|
||||
filters = this.options.filters;
|
||||
if ( 'uploaded' === filters ) {
|
||||
FiltersConstructor = media.view.AttachmentFilters.Uploaded;
|
||||
@ -5616,6 +5675,7 @@
|
||||
selection: this.options.selection,
|
||||
model: this.model,
|
||||
sortable: this.options.sortable,
|
||||
showAttachmentFields: this.options.showAttachmentFields,
|
||||
|
||||
// The single `Attachment` view to be used in the `Attachments` view.
|
||||
AttachmentView: this.options.AttachmentView
|
||||
|
@ -220,6 +220,15 @@ function wp_print_media_templates() {
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="tmpl-media-library-view-switcher">
|
||||
<a href="<?php echo esc_url( add_query_arg( 'mode', 'list', $_SERVER['REQUEST_URI'] ) ) ?>" class="view-list">
|
||||
<img id="view-switch-list" src="<?php echo includes_url( 'images/blank.gif' ) ?>" width="20" height="20" title="List View" alt="List View"/>
|
||||
</a>
|
||||
<a href="<?php echo esc_url( add_query_arg( 'mode', 'grid', $_SERVER['REQUEST_URI'] ) ) ?>" class="view-grid current">
|
||||
<img id="view-switch-excerpt" src="<?php echo includes_url( 'images/blank.gif' ) ?>" width="20" height="20" title="Grid View" alt="Grid View"/>
|
||||
</a>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="tmpl-uploader-status">
|
||||
<h3><?php _e( 'Uploading' ); ?></h3>
|
||||
<a class="upload-dismiss-errors" href="#"><?php _e('Dismiss Errors'); ?></a>
|
||||
@ -241,7 +250,128 @@ function wp_print_media_templates() {
|
||||
<span class="upload-error-message">{{ data.message }}</span>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="tmpl-edit-attachment-frame">
|
||||
<div class="edit-media-header">
|
||||
<button class="left dashicons dashicons-no<# if ( ! data.hasPrevious ) { #> disabled <# } #>"><span class="screen-reader-text"><?php _e( 'Edit previous media item' ); ?></span></button>
|
||||
<button class="right dashicons dashicons-no<# if ( ! data.hasNext ) { #> disabled <# } #>"><span class="screen-reader-text"><?php _e( 'Edit next media item' ); ?></span></button>
|
||||
</div>
|
||||
<div class="media-frame-router"></div>
|
||||
<div class="media-frame-content"></div>
|
||||
<div class="media-frame-toolbar"></div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="tmpl-attachment-details-two-column">
|
||||
<h3>
|
||||
<?php _e('Attachment Details'); ?>
|
||||
|
||||
<span class="settings-save-status">
|
||||
<span class="spinner"></span>
|
||||
<span class="saved"><?php esc_html_e('Saved.'); ?></span>
|
||||
</span>
|
||||
</h3>
|
||||
<div class="attachment-info">
|
||||
<div class="thumbnail thumbnail-{{ data.type }}">
|
||||
<# if ( data.uploading ) { #>
|
||||
<div class="media-progress-bar"><div></div></div>
|
||||
<# } else if ( 'image' === data.type ) { #>
|
||||
<img src="{{ data.sizes.full.url }}" draggable="false" />
|
||||
<# } else { #>
|
||||
<img src="{{ data.icon }}" class="icon" draggable="false" />
|
||||
<# } #>
|
||||
</div>
|
||||
<div class="details">
|
||||
<div class="filename">{{ data.filename }}</div>
|
||||
<div class="uploaded">{{ data.dateFormatted }}</div>
|
||||
|
||||
<div class="file-size">{{ data.filesizeHumanReadable }}</div>
|
||||
<# if ( 'image' === data.type && ! data.uploading ) { #>
|
||||
<# if ( data.width && data.height ) { #>
|
||||
<div class="dimensions">{{ data.width }} × {{ data.height }}</div>
|
||||
<# } #>
|
||||
|
||||
<# if ( data.can.save ) { #>
|
||||
<a class="edit-attachment" href="{{ data.editLink }}&image-editor" target="_blank"><?php _e( 'Edit Image' ); ?></a>
|
||||
<a class="refresh-attachment" href="#"><?php _e( 'Refresh' ); ?></a>
|
||||
<# } #>
|
||||
<# } #>
|
||||
|
||||
<# if ( data.fileLength ) { #>
|
||||
<div class="file-length"><?php _e( 'Length:' ); ?> {{ data.fileLength }}</div>
|
||||
<# } #>
|
||||
|
||||
<# if ( ! data.uploading && data.can.remove ) { #>
|
||||
<?php if ( MEDIA_TRASH ): ?>
|
||||
<a class="trash-attachment" href="#"><?php _e( 'Trash' ); ?></a>
|
||||
<?php else: ?>
|
||||
<a class="delete-attachment" href="#"><?php _e( 'Delete Permanently' ); ?></a>
|
||||
<?php endif; ?>
|
||||
<# } #>
|
||||
|
||||
<div class="compat-meta">
|
||||
<# if ( data.compat && data.compat.meta ) { #>
|
||||
{{{ data.compat.meta }}}
|
||||
<# } #>
|
||||
</div>
|
||||
</div>
|
||||
<# if ( 'audio' === data.type ) { #>
|
||||
<div class="wp-media-wrapper">
|
||||
<audio style="visibility: hidden" controls class="wp-audio-shortcode" width="100%" preload="none">
|
||||
<source type="{{ data.mime }}" src="{{ data.url }}"/>
|
||||
</audio>
|
||||
</div>
|
||||
<# } else if ( 'video' === data.type ) { #>
|
||||
<div style="max-width: 100%; width: {{ data.width }}px" class="wp-media-wrapper">
|
||||
<video controls class="wp-video-shortcode" preload="metadata"
|
||||
width="{{ data.width }}" height="{{ data.height }}"
|
||||
<# if ( data.image && data.image.src !== data.icon ) { #>poster="{{ data.image.src }}"<# } #>>
|
||||
<source type="{{ data.mime }}" src="{{ data.url }}"/>
|
||||
</video>
|
||||
</div>
|
||||
<# } #>
|
||||
</div>
|
||||
<div class="attachment-fields">
|
||||
<label class="setting" data-setting="url">
|
||||
<span class="name"><?php _e('URL'); ?></span>
|
||||
<input type="text" value="{{ data.url }}" readonly />
|
||||
</label>
|
||||
<# var maybeReadOnly = data.can.save || data.allowLocalEdits ? '' : 'readonly'; #>
|
||||
<label class="setting" data-setting="title">
|
||||
<span class="name"><?php _e('Title'); ?></span>
|
||||
<input type="text" value="{{ data.title }}" {{ maybeReadOnly }} />
|
||||
</label>
|
||||
<label class="setting" data-setting="caption">
|
||||
<span class="name"><?php _e('Caption'); ?></span>
|
||||
<textarea {{ maybeReadOnly }}>{{ data.caption }}</textarea>
|
||||
</label>
|
||||
<# if ( 'image' === data.type ) { #>
|
||||
<label class="setting" data-setting="alt">
|
||||
<span class="name"><?php _e('Alt Text'); ?></span>
|
||||
<input type="text" value="{{ data.alt }}" {{ maybeReadOnly }} />
|
||||
</label>
|
||||
<# } #>
|
||||
<label class="setting" data-setting="description">
|
||||
<span class="name"><?php _e('Description'); ?></span>
|
||||
<textarea {{ maybeReadOnly }}>{{ data.description }}</textarea>
|
||||
</label>
|
||||
<label class="setting">
|
||||
<span class="name"><?php _e( 'Uploaded By' ); ?></span>
|
||||
<span class="value">{{ data.authorName }}</span>
|
||||
</label>
|
||||
<# if ( data.uploadedTo ) { #>
|
||||
<label class="setting">
|
||||
<span class="name"><?php _e('Uploaded To'); ?></span>
|
||||
<span class="value"><a href="{{ data.uploadedToLink }}">{{ data.uploadedToTitle }}</a></span>
|
||||
</label>
|
||||
<# } #>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="tmpl-attachment">
|
||||
<# if ( _.contains( data.controller.options.mode, 'grid' ) ) { #>
|
||||
<div class="inline-toolbar">
|
||||
<div class="dashicons dashicons-edit edit edit-media"></div>
|
||||
</div>
|
||||
<# } #>
|
||||
<div class="attachment-preview type-{{ data.type }} subtype-{{ data.subtype }} {{ data.orientation }}">
|
||||
<# if ( data.uploading ) { #>
|
||||
<div class="media-progress-bar"><div></div></div>
|
||||
@ -251,13 +381,15 @@ function wp_print_media_templates() {
|
||||
<img src="{{ data.size.url }}" draggable="false" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<# } else { #>
|
||||
<# } else {
|
||||
if ( data.thumb && data.thumb.src && data.thumb.src !== data.icon ) {
|
||||
#><img src="{{ data.thumb.src }}" class="thumbnail" draggable="false" /><#
|
||||
} #>
|
||||
<img src="{{ data.icon }}" class="icon" draggable="false" />
|
||||
<div class="filename">
|
||||
<div>{{ data.filename }}</div>
|
||||
</div>
|
||||
<# } #>
|
||||
|
||||
<# if ( data.buttons.close ) { #>
|
||||
<a class="close media-modal-icon" href="#" title="<?php esc_attr_e('Remove'); ?>"></a>
|
||||
<# } #>
|
||||
@ -268,8 +400,8 @@ function wp_print_media_templates() {
|
||||
</div>
|
||||
<#
|
||||
var maybeReadOnly = data.can.save || data.allowLocalEdits ? '' : 'readonly';
|
||||
if ( data.describe ) { #>
|
||||
<# if ( 'image' === data.type ) { #>
|
||||
if ( data.describe ) {
|
||||
if ( 'image' === data.type ) { #>
|
||||
<input type="text" value="{{ data.caption }}" class="describe" data-setting="caption"
|
||||
placeholder="<?php esc_attr_e('Caption this image…'); ?>" {{ maybeReadOnly }} />
|
||||
<# } else { #>
|
||||
@ -281,8 +413,31 @@ function wp_print_media_templates() {
|
||||
<# } else { #>
|
||||
placeholder="<?php esc_attr_e('Describe this media file…'); ?>"
|
||||
<# } #> {{ maybeReadOnly }} />
|
||||
<# }
|
||||
}
|
||||
|
||||
if ( _.contains( data.controller.options.mode, 'grid' ) ) { #>
|
||||
<div class="data-fields">
|
||||
<# _.each( data.showAttachmentFields, function( field ) { #>
|
||||
<div class="data-field data-{{ field }}"><#
|
||||
if ( 'uploadedTo' === field ) {
|
||||
if ( data[field] ) {
|
||||
#><?php _e( 'Uploaded To:' ) ?><#
|
||||
} else {
|
||||
#><?php _e( 'Unattached' ) ?><#
|
||||
}
|
||||
} else if ( 'title' === field && ! data[ field ] ) {
|
||||
#><?php _e( '(No title)' ) ?><#
|
||||
}
|
||||
|
||||
if ( data[ field ] ) {
|
||||
#>{{ data[ field ] }}<#
|
||||
}
|
||||
#></div>
|
||||
<# }); #>
|
||||
</div>
|
||||
<# } #>
|
||||
<# } #>
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="tmpl-attachment-details">
|
||||
|
Loading…
Reference in New Issue
Block a user