Ok here is my code - stock standard and works if I simply select an existing image
jQuery(function($){
var file_frame;
$('#upload-button').on( 'click', function( e ){
e.preventDefault();
// If the media frame already exists, reopen it.
if ( file_frame ) {
file_frame.open();
return;
}
// Create a new media frame
file_frame = wp.media({
title: 'Select or Upload Media Of Your Chosen Persuasion',
button: {
text: 'Use this media'
},
multiple: false // Set to true to allow multiple files to be selected
});
file_frame.on('open', function(){
console.log("inside open");
});
file_frame.on('update', function(){
console.log("inside update");
});
file_frame.on('select', function(){
// This will return the selected image from the Media Uploader, the result is an object
var uploaded_image = file_frame.state().get('selection').first();
// We convert uploaded_image to a JSON object to make accessing it easier
// Output to the console uploaded_image
console.log(uploaded_image);
var image_url = uploaded_image.toJSON().url;
// Let's assign the url value to the input field
$('#image-url').val(image_url);
});
file_frame.open();
});
});
But if I goto drag and drop an image in there the image is uploaded but an error is returned
"An error occurred in the upload. Please try again later."
What have I missed, I'm assuming its some kind of refresh for the existing media selection window and my googling has not turned up anything.
Cheers
EDIT
I have tried several things to get the uploaded image to be shown in the media frame once uploaded. Not having much success.
As I said it appears the image is uploaded and added to the media library but I am missing a refresh or reload of the frame to show the image.
Any one have experience with or know another place to go look?
Maybe this call when everything is 'done':
if(wp.media.frame.library) wp.media.frame.library.props.set({ignore: (+ new Date())});
Or if you need to separate the library Grid modal from media upload (edit post) modal:
if(wp.media.frame.library){
wp.media.frame.library.props.set({ignore: (+ new Date())});
} else if(wp.media.frame.content.get().collection){
wp.media.frame.content.get().collection.props.set({ignore: (+ new Date())});
wp.media.frame.content.get().options.selection.reset();
}
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/
I'm relatively new to WP. In fact, I'm building my first WP theme and I'm stuck on the same question as you. Thank to your code, I can get to the Gallery page. And luckily, I've got the images saved. Here's my code:
// when click Insert Gallery, run callback
wp_media_frame.on('update', function(){
var library = wp_media_frame.state().get('library');
var images = [];
var image_ids = [];
thumb_wraper.html('');
library.map( function( image ) {
image = image.toJSON();
images.push(image.url);
image_ids.push(image.id);
thumb_wraper.append('<img src="' + image.url + '" alt="" />');
});
});
What I have found is you should get 'library' instead of get 'selection'.
Edit:
I've figured out how to go back to gallery-edit. Here is my full code:
$( '#btn_upload' ).on( 'click', function( event ) {
event.preventDefault();
var images = $( '#image_ids' ).val();
var gallery_state = images ? 'gallery-edit' : 'gallery-library';
// create new media frame
// You have to create new frame every time to control the Library state as well as selected images
var wp_media_frame = wp.media.frames.wp_media_frame = wp.media( {
title: 'My Gallery', // it has no effect but I really want to change the title
frame: "post",
toolbar: 'main-gallery',
state: gallery_state,
library: {
type: 'image'
},
multiple: true
} );
// when open media frame, add the selected image to Gallery
wp_media_frame.on( 'open', function() {
var images = $( '#image_ids' ).val();
if ( !images )
return;
var image_ids = images.split( ',' );
var library = wp_media_frame.state().get( 'library' );
image_ids.forEach( function( id ) {
attachment = wp.media.attachment( id );
attachment.fetch();
library.add( attachment ? [ attachment ] : [] );
} );
} );
// when click Insert Gallery, run callback
wp_media_frame.on( 'update', function() {
var thumb_wrapper = $( '#thumb-wrapper' );
thumb_wraper.html( '' );
var image_urls = [];
var image_ids = [];
var library = wp_media_frame.state().get( 'library' );
library.map( function( image ) {
image = image.toJSON();
image_urls.push( image.url );
image_ids.push( image.id );
thumb_wrapper.append( '<img src="' + image.url + '" alt="" />' );
} );
} );
} );
I figured that if you re-open the existed frame, it'll always keep the initial state, in your case it's 'gallery'. You'll have to create new frame every time and check if there's images to open 'gallery-edit'
Also, I prefer 'gallery-library' than 'gallery' because I want user to focus on my gallery.
I am trying to send an image name using aviary and need the image name included. I have a hidden field in my form "img" Here is the code:
<script type='text/javascript'>
var featherEditor = new Aviary.Feather({
apiKey: 'yogbsxxxxxxxx4',
apiVersion: 3,
theme: 'dark', // Check out our new 'light' and 'dark' themes!
tools: 'enhance,crop,orientation,brightness,sharpness,redeye,resize,text',
appendTo: '',
onSave: function(imageID, newURL) {
var img = document.getElementById(imageID);
img.src = newURL;
},
onError: function(errorObj) {
alert(errorObj.message);
},
postUrl: 'http://xxxxx/~gsidev/gallery/post.php',
postData : document.getElementById(img),// this is the field I need and does not work?
});
function launchEditor(id, src) {
featherEditor.launch({
image: id,
url: src
});
return false;
}
</script>
Thanks for any guidance. The support for php implementation is terrible on Aviary...
Figured it out! I added a new variable and passed it. This will send the file name in php and overwrite the existing file providing your post url file is inside the same folder as the your image you called for the editor.
function launchEditor(id, src, img) {
featherEditor.launch({
image: id,
url: src,
postData : img
});
return false;
}
</script>
Now on the save page :
$image_data = file_get_contents($_REQUEST['url']);
file_put_contents(($_REQUEST['postData']),$image_data);
?>
And change the link or button code to match
<!-- Add an edit button, passing the HTML id of the image
and the public URL to the image -->
<a href="#" onclick="return launchEditor('editableimage1',"imagename.jpg"
'http://example.com/public/images/goat.jpg');">Edit!</a>
I want to create a button on imperavi's redactor, that will display uploaded files (only photos) in a modal, that i previously uploaded, and i will allow the user, to organize this photos, order their order and organize them in folders, and create folders. And when the user select the photo, the tag is inserted in the text field (redactor).
I rely want a place to begin, or a already existing solution, my knowledge with php is big but my jquery and ajax is very small
I don't want to display the computer folder, i want to display the images int the database
Sorry for the bad English.
Where do i begin?
edit 1:
I manged to add the button
if (typeof RedactorPlugins === 'undefined') var RedactorPlugins = {};
RedactorPlugins.myPlugin = {
init: function() {
this.addBtn('myMethod', 'Add Image', function(obj) {
obj.myMethod();
});
},
myMethod: function()
{
// callback (optional)
var callback = $.proxy(function()
{
return 1;
}, this);
var modal = String() +
'<div id="redactor_modal_content">' +
'<div class="modal-body">' +
'<p>One fine body...</p>' +
'</div>' +
'<div id="redactor_modal_footer">' +
'Close' +
'Save changes' +
'</div>' +
'</div>';
// 500 it is the width of the window in pixels
// or call a modal with a code
this.modalInit('<h3>Modal header</h3>', modal, 500, callback);
// call a modal from element with ID #mymodal
//this.modalInit('<h3>Modal header</h3>', '#mymodal', 500, callback);
}
}
How it works:
I'm trying to create an instant upload function with Jquery/Ajax. When a user double-clicks an image, a Fancybox shows up with the upload field. After choosing an image, the image is uploaded and the source of the clicked image is changed immediately.
The problem:
When having multiple images on one page, sometimes another image gets replaced by the new image (randomly).
The code:
function uploader(thumb) {
new AjaxUpload('imageUpload', {
action: 'uploader.php',
name: 'file',
onComplete: function(file, response) {
thumb.attr('src', response);
$.fancybox.close();
}
});
}
$("img").dblclick(function(){
var img = $(this);
$.fancybox({
href: '#imageUpload',
overlayShow: true
});
uploader(img);
return false;
});
What I've tried:
When I alert the ID of the image that should be replaced, it always alerts the correct ID of the image. And still it replaces another image instead.
Regards,
Bo
The way you're getting a reference to the clicked image is not good. You should extract the clicked element from the event object passed to the handler.
$('img').dblclick(function(event) {
var img = $(event.target);
...
});