diff --git a/wp-includes/css/media-views.css b/wp-includes/css/media-views.css
index cca93fa56f..209d41620a 100644
--- a/wp-includes/css/media-views.css
+++ b/wp-includes/css/media-views.css
@@ -271,6 +271,10 @@
*max-width: 55%; /* IE7 */
}
+.media-sidebar .setting input[type="checkbox"] {
+ margin-top: 10px;
+}
+
.media-sidebar .setting span,
.compat-item label span {
float: left;
diff --git a/wp-includes/js/media-editor.js b/wp-includes/js/media-editor.js
index 2a3cfd540b..64081c7d73 100644
--- a/wp-includes/js/media-editor.js
+++ b/wp-includes/js/media-editor.js
@@ -189,6 +189,10 @@
args.type = 'image';
args.perPage = -1;
+ // Mark the `orderby` override attribute.
+ if ( 'rand' === attrs.orderby )
+ attrs._orderbyRandom = true;
+
// Map the `orderby` attribute to the corresponding model property.
if ( ! attrs.orderby || /^menu_order(?: ID)?$/i.test( attrs.orderby ) )
args.orderby = 'menuOrder';
@@ -232,6 +236,11 @@
if ( props.uploadedTo )
attrs.id = props.uploadedTo;
+ // Check if the gallery is randomly ordered.
+ if ( attrs._orderbyRandom )
+ attrs.orderby = 'rand';
+ delete attrs._orderbyRandom;
+
// If the `ids` attribute is set and `orderby` attribute
// is the default value, clear it for cleaner output.
if ( attrs.ids && 'post__in' === attrs.orderby )
diff --git a/wp-includes/js/media-models.js b/wp-includes/js/media-models.js
index cb4b6b6ecd..c64a023fa1 100644
--- a/wp-includes/js/media-models.js
+++ b/wp-includes/js/media-models.js
@@ -832,35 +832,12 @@ window.wp = window.wp || {};
// If the workflow does not support multiple
// selected attachments, reset the selection.
add: function( models, options ) {
- if ( ! this.multiple ) {
- models = _.isArray( models ) && models.length ? _.first( models ) : models;
- this.clear( options );
- }
+ if ( ! this.multiple )
+ this.remove( this.models );
return Attachments.prototype.add.call( this, models, options );
},
- // Removes all models from the selection.
- clear: function( options ) {
- this.remove( this.models, options ).single();
- return this;
- },
-
- // Override the selection's reset method.
- // Always direct items through add and remove,
- // as we need them to fire.
- reset: function( models, options ) {
- this.clear( options ).add( models, options ).single();
- return this;
- },
-
- // Create selection.has, which determines if a model
- // exists in the collection based on cid and id,
- // instead of direct comparison.
- has: function( attachment ) {
- return !! ( this.getByCid( attachment.cid ) || this.get( attachment.id ) );
- },
-
single: function( model ) {
var previous = this._single;
@@ -869,7 +846,7 @@ window.wp = window.wp || {};
this._single = model;
// If the single model isn't in the selection, remove it.
- if ( this._single && ! this.has( this._single ) )
+ if ( this._single && ! this.getByCid( this._single.cid ) )
delete this._single;
this._single = this._single || this.last();
diff --git a/wp-includes/js/media-views.js b/wp-includes/js/media-views.js
index 3bc1fb0497..7e8444cd51 100644
--- a/wp-includes/js/media-views.js
+++ b/wp-includes/js/media-views.js
@@ -329,7 +329,7 @@
},
reset: function() {
- this.get('selection').clear();
+ this.get('selection').reset();
this.resetDisplays();
},
@@ -534,20 +534,32 @@
},
gallerySettings: function() {
- var library = this.get('library');
+ var library = this.get('library'),
+ browser;
if ( ! library )
return;
library.gallery = library.gallery || new Backbone.Model();
- this.frame.content.view().sidebar.set({
+ browser = this.frame.content.view();
+
+ browser.sidebar.set({
gallery: new media.view.Settings.Gallery({
controller: this,
model: library.gallery,
priority: 40
})
});
+
+ browser.toolbar.set( 'reverse', {
+ text: l10n.reverseOrder,
+ priority: 80,
+
+ click: function() {
+ library.reset( library.toArray().reverse() );
+ }
+ });
}
});
@@ -2505,12 +2517,18 @@
buttons: {},
initialize: function() {
+ var selection = this.options.selection;
+
this.controller = this.options.controller;
this.model.on( 'change:sizes change:uploading change:caption change:title', this.render, 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 );
+ if ( selection )
+ selection.on( 'reset', this.updateSelect, this );
// Update the model's details view.
this.model.on( 'selection:single selection:unsingle', this.details, this );
@@ -2518,7 +2536,14 @@
},
dispose: function() {
+ var selection = this.options.selection;
+
+ // Make sure all settings are saved before removing the view.
this.updateAll();
+
+ if ( selection )
+ selection.off( null, null, this );
+
media.View.prototype.dispose.apply( this, arguments );
return this;
},
@@ -2557,8 +2582,7 @@
delete this.$bar;
// Check if the model is selected.
- if ( this.selected() )
- this.select();
+ this.updateSelect();
this.views.render();
return this;
@@ -2576,7 +2600,7 @@
if ( ! selection )
return;
- if ( selection.has( model ) ) {
+ if ( this.selected() ) {
// If the model is the single model, remove it.
// If it is not the same as the single model,
// it now becomes the single model.
@@ -2586,10 +2610,14 @@
}
},
+ updateSelect: function() {
+ this[ this.selected() ? 'select' : 'deselect' ]();
+ },
+
selected: function() {
var selection = this.options.selection;
if ( selection )
- return selection.has( this.model );
+ return !! selection.getByCid( this.model.cid );
},
select: function( model, collection ) {
@@ -3312,7 +3340,7 @@
clear: function( event ) {
event.preventDefault();
- this.collection.clear();
+ this.collection.reset();
}
});
@@ -3388,7 +3416,7 @@
clear: function( event ) {
event.preventDefault();
- this.collection.clear();
+ this.collection.reset();
}
});
@@ -3468,6 +3496,10 @@
} else if ( $setting.is('input[type="text"], textarea') ) {
if ( ! $setting.is(':focus') )
$setting.val( value );
+
+ // Handle checkboxes.
+ } else if ( $setting.is('input[type="checkbox"]') ) {
+ $setting.attr( 'checked', !! value );
}
},
@@ -3481,6 +3513,11 @@
if ( ! $setting.length )
return;
+ // Use the correct value for checkboxes.
+ if ( $setting.is('input[type="checkbox"]') )
+ value = $setting[0].checked;
+
+ // Update the corresponding setting.
this.model.set( $setting.data('setting'), value );
// If the setting has a corresponding user setting,
@@ -3550,15 +3587,15 @@
$input.show();
- if ( 'post' == linkTo ) {
+ if ( 'post' === linkTo ) {
$input.val( attachment.get('link') );
- } else if ( 'file' == linkTo ) {
+ } else if ( 'file' === linkTo ) {
$input.val( attachment.get('url') );
} else if ( ! this.model.get('linkUrl') ) {
$input.val('http://');
}
- $input.prop('readonly', 'custom' !== linkTo);
+ $input.prop( 'readonly', 'custom' !== linkTo );
// If the input is visible, focus and select its contents.
if ( $input.is(':visible') )
diff --git a/wp-includes/media.php b/wp-includes/media.php
index 29c4b7d1fc..1e0ee12d34 100644
--- a/wp-includes/media.php
+++ b/wp-includes/media.php
@@ -670,8 +670,9 @@ function gallery_shortcode($attr) {
$instance++;
if ( ! empty( $attr['ids'] ) ) {
- // 'ids' is explicitly ordered
- $attr['orderby'] = 'post__in';
+ // 'ids' is explicitly ordered, unless you specify otherwise.
+ if ( empty( $attr['orderby'] ) )
+ $attr['orderby'] = 'post__in';
$attr['include'] = $attr['ids'];
}
@@ -1489,6 +1490,7 @@ function wp_enqueue_media( $args = array() ) {
'updateGallery' => __( 'Update gallery' ),
'continueEditing' => __( 'Continue editing' ),
'addToGallery' => __( 'Add to gallery' ),
+ 'reverseOrder' => __( 'Reverse order' ),
);
$settings = apply_filters( 'media_view_settings', $settings, $post );
@@ -1865,6 +1867,11 @@ function wp_print_media_templates() {
+
+