When I click the Add Media button on a Post/Page, I have the option to Add Media. After selecting media, I click Insert Into Post, and the images are inserted. However, there is another option, which is on the left sidebar. I can click Create Gallery. The image selecting process is the same, but when I click Create New Gallery, it goes to a new frame which allows me to edit the order of the images.
This second window is what I am after. I am calling the frame from a metabox, and I have gotten it successfully to allow me to grab single or multiple images and save the ID's as a string, as well as insert thumbnails live into a preview box. I cannot find anything about calling the Gallery frame.
My current code is as follows:
jQuery('#fg_select').on('click', function(event){
event.preventDefault();
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frame = wp.media({
title: "Select Images For Gallery",
button: {text: "Select",},
library : { type : 'image'},
multiple: true // Set to true to allow multiple files to be selected
});
file_frame.on('open', function() {
var selection = file_frame.state().get('selection');
ids = jQuery('#fg_metadata').val().split(',');
ids.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
});
file_frame.on('ready', function() {
// Here we can add a custom class to our media modal.
// .media-modal doesn't exists before the frame is
// completly initialised.
$( '.media-modal' ).addClass( 'no-sidebar' );
});
// When an image is selected, run a callback.
file_frame.on('select', function() {
var imageIDArray = [];
var imageHTML = '';
var metadataString = '';
images = file_frame.state().get('selection');
images.each(function(image) {
imageIDArray.push(image.attributes.id);
imageHTML += '<li><button></button><img id="'+image.attributes.id+'" src="'+image.attributes.url+'"></li>';
});
metadataString = imageIDArray.join(",");
if(metadataString){
jQuery("#fg_metadata").val(metadataString);
jQuery("#featuredgallerydiv ul").html(imageHTML);
jQuery('#fg_select').text('Edit Selection');
jQuery('#fg_removeall').addClass('visible');
}
});
// Finally, open the modal
file_frame.open();
});
Any ideas?
EDIT:
I've gotten it to the point where it calls the gallery directly, without any sidebars, etc. However, it now ignores the on('select') call. I guess galleries send a different call when selecting the image?
jQuery(document).ready(function($){
// Uploading files
var file_frame;
jQuery('#fg_select').on('click', function(event){
event.preventDefault();
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frame = wp.media({
frame: "post",
state: "featured-gallery",
library : { type : 'image'},
button: {text: "Edit Image Order"},
multiple: true
});
file_frame.states.add([
new wp.media.controller.Library({
id: 'featured-gallery',
title: 'Select Images for Gallery',
priority: 20,
toolbar: 'main-gallery',
filterable: 'uploaded',
library: wp.media.query( file_frame.options.library ),
multiple: file_frame.options.multiple ? 'reset' : false,
editable: true,
allowLocalEdits: true,
displaySettings: true,
displayUserSettings: true
}),
]);
file_frame.on('open', function() {
var selection = file_frame.state().get('selection');
ids = jQuery('#fg_metadata').val().split(',');
if (!empty(ids)) {
ids.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
}
});
file_frame.on('ready', function() {
// Here we can add a custom class to our media modal.
// .media-modal doesn't exists before the frame is
// completly initialised.
$( '.media-modal' ).addClass( 'no-sidebar' );
});
file_frame.on('change', function() {
// Here we can add a custom class to our media modal.
// .media-modal doesn't exists before the frame is
// completly initialised.
setTimeout(function(){
$('.media-menu a:first-child').text('← Edit Selection').addClass('button').addClass('button-large').addClass('button-primary');
},0);
});
// When an image is selected, run a callback.
file_frame.on('set', function() {
alert('test');
});
// Finally, open the modal
file_frame.open();
});
EDIT 2:
Okay, so I've gotten everything to fire correctly. But I can't decipher the outputted gallery code.
// When an image is selected, run a callback.
file_frame.on('update', function() {
var imageIDArray = [];
var imageHTML = '';
var metadataString = '';
images = file_frame.state().get('selection');
images.each(function(image) {
imageIDArray.push(image.attributes.id);
imageHTML += '<li><button></button><img id="'+image.attributes.id+'" src="'+image.attributes.url+'"></li>';
});
metadataString = imageIDArray.join(",");
if (metadataString) {
jQuery("#fg_metadata").val(metadataString);
jQuery("#featuredgallerydiv ul").html(imageHTML);
jQuery('#fg_select').text('Edit Selection');
jQuery('#fg_removeall').addClass('visible');
}
});
Nothing is coming out for $imageArray, or $imageHTML. $image is something, it's an [object object].
EDIT 3: As mentioned below in comment, the main problem with the code from Edit 2 is that when using Gallery, you have to call 'library' instead of 'selection'.
// Uploading files
var file_frame;
jQuery('#fg_select').on('click', function(event){
event.preventDefault();
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create the media frame.
file_frame = wp.media.frame = wp.media({
frame: "post",
state: "gallery",
library : { type : 'image'},
button: {text: "Edit Image Order"},
multiple: true
});
file_frame.on('open', function() {
var selection = file_frame.state().get('selection');
var ids = jQuery('#fg_metadata').val();
if (ids) {
idsArray = ids.split(',');
idsArray.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
}
});
// When an image is selected, run a callback.
file_frame.on('update', function() {
var imageIDArray = [];
var imageHTML = '';
var metadataString = '';
images = file_frame.state().get('library');
images.each(function(attachment) {
imageIDArray.push(attachment.attributes.id);
imageHTML += '<li><button></button><img id="'+attachment.attributes.id+'" src="'+attachment.attributes.url+'"></li>';
});
metadataString = imageIDArray.join(",");
if (metadataString) {
jQuery("#fg_metadata").val(metadataString);
jQuery("#featuredgallerydiv ul").html(imageHTML);
jQuery('#fg_select').text('Edit Selection');
jQuery('#fg_removeall').addClass('visible');
}
});
// Finally, open the modal
file_frame.open();
});
The main thing here I'm having difficulty with now is that I can't get it to open to gallery-edit with a selection. I can get it to open there, but there are no images selected. I'm looking into that. I'm also looking into re-opening instead of creating a new view and sending a pre-selection. If I go to the selection window, then the order window, but click the X to close, I can re-open to the order window. So there should be a way.
EDIT 4
As per code from answer below, I've changed the pre-selection code to:
file_frame.on('open', function() {
var library = file_frame.state().get('library');
var ids = jQuery('#fg_perm_metadata').val();
if (ids) {
idsArray = ids.split(',');
idsArray.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
library.add( attachment ? [ attachment ] : [] );
});
}
});
This allows me to re-open directly to the gallery-edit state and have images pre-selected. However, when I open directly to this state, I cannot click Cancel Gallery (return to image selection state). Clicking that button/link just closes the frame. I tried pre-filling both the library and the selection, but that doesn't work either. The following is from media-views.js, and seems to be what controls that button. Instead of changing the state to a specific state, it changes it to the previous state. Since we are opening directly to gallery-edit, there is no past state. I'm wondering if it's possible to open to gallery, and then on open, change to gallery-edit. Do it instantly so that the user doesn't see, but so that it gets the past state into the system.
galleryMenu: function( view ) {
var lastState = this.lastState(),
previous = lastState && lastState.id,
frame = this;
EDIT 5:
Finally figured it all out. I couldn't get the above to work at all, I'm not sure why. So, there may be a better way to do this, involving that code. If so, I'd love to know.
file_frame.on('open', function() {
var selection = file_frame.state().get('selection');
var library = file_frame.state('gallery-edit').get('library');
var ids = jQuery('#fg_perm_metadata').val();
if (ids) {
idsArray = ids.split(',');
idsArray.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
selection.add( attachment ? [ attachment ] : [] );
});
file_frame.setState('gallery-edit');
idsArray.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
library.add( attachment ? [ attachment ] : [] );
});
}
});
FINAL EDIT
My code is now working entirely, and I appreciate the help! If you'd like to see it in action, check out http://wordpress.org/plugins/featured-galleries/