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();
}
I've got a front-end uploader that allows users to upload images to a post. When they click the upload button that opens up the gallery they are able to see every image in the galllery, not just the ones tied to that specific post. I'd like to change that. I'd like when a user is in a post trying to upload an image, they can not see images tied to another post.
I've googled all I can think of and can't find a solution.
Here's my code:
var image_custom_uploader_2;
var $thisItem = '';
jQuery(document).on('click', '.avatar-upload-image', function(e) {
e.preventDefault();
$thisItem = jQuery(this);
//If the uploader object has already been created, reopen the dialog
if (image_custom_uploader_2) {
image_custom_uploader_2.open();
return;
}
//Extend the wp.media object
image_custom_uploader_2 = wp.media.frames.file_frame = wp.media({
title: 'Choose Image',
button: {
text: 'Choose Image'
},
multiple: false
});
console.log(image_custom_uploader_2);
//When a file is selected, grab the URL and set it as the text field's value
image_custom_uploader_2.on('select', function() {
attachment = image_custom_uploader_2.state().get('selection').first().toJSON();
var url = '';
url = attachment['url'];
var attachId = '';
attachId = attachment['id'];
$thisItem.parent().find('.listing-upload-gallery-image-data-url').val(url);
$thisItem.parent().find('.listing-upload-gallery-image-data-id').val(attachId);
$thisItem.parent().find(".gallery-image-holder").css("background-image", "url(" + url + ")");
$thisItem.parent().find(".avatar-upload-image").css("display", "none");
$thisItem.parent().find(".avatar-delete-image").css("display", "inline-block");
});
//Open the uploader dialog
image_custom_uploader_2.open();
});
jQuery(document).on('click', '.avatar-delete-image', function(e) {
jQuery(this).parent().find('.listing-upload-gallery-image-data-url').val('');
jQuery(this).parent().find('.listing-upload-gallery-image-data-id').val('');
jQuery(this).parent().find(".gallery-image-holder").css("background-image", "none");
jQuery(this).parent().find(".avatar-upload-image").css("display", "inline-block");
jQuery(this).css("display", "none");
});
I have a feeling I need to somehow incorporate one of the following:
uploadedTo :
post_parent :
but I'm not sure how to apply a post ID to them when this would be on a brand new, unsaved post
EDIT:
uploadedTo : wp.media.view.settings.post.id
uploadedTo : $post-id
Still allow all the other media items to be seen on the post's media library
I'm creating a plugin and i have an admin page
In the options of that page, i would like to add a button that allow me to open the Wordpress media library and select an image from it, after that, get the URL of the selected image and the alt attribute.
If it is possible, how can i do that using AJAX?
First you would need to enqueue wordpress core media scripts and a custom js script
function my_enqueue_media_lib_uploader() {
//Core media script
wp_enqueue_media();
// Your custom js file
wp_register_script( 'media-lib-uploader-js', plugins_url( 'media-lib-uploader.js' , __FILE__ ), array('jquery') );
wp_enqueue_script( 'media-lib-uploader-js' );
}
add_action('admin_enqueue_scripts', 'my_enqueue_media_lib_uploader');
Then let say you have this markup within your options page: an upload button and a text input to store the selected image url
<form method="post">
<input id="image-url" type="text" name="image" />
<input id="upload-button" type="button" class="button" value="Upload Image" />
<input type="submit" value="Submit" />
</form>
You need to add this javascript code to invoke the uploader popup
jQuery(document).ready(function($){
var mediaUploader;
$('#upload-button').click(function(e) {
e.preventDefault();
// If the uploader object has already been created, reopen the dialog
if (mediaUploader) {
mediaUploader.open();
return;
}
// Extend the wp.media object
mediaUploader = wp.media.frames.file_frame = wp.media({
title: 'Choose Image',
button: {
text: 'Choose Image'
}, multiple: false });
// When a file is selected, grab the URL and set it as the text field's value
mediaUploader.on('select', function() {
attachment = mediaUploader.state().get('selection').first().toJSON();
$('#image-url').val(attachment.url);
});
// Open the uploader dialog
mediaUploader.open();
});
});
Once the image is selected, your image-url input will now contain the url and will be saved on form submit.
The use case is: I have plugin that contain index.php as main file, I want to be able to click on a button and the media library opened and select an image from it, this image should be load into an image tag.
1- add script to your main PHP plugin
// index.php
// ...
// add script js for page
add_action('admin_enqueue_scripts', function () {
// Enqueue WordPress media scripts
if ($_GET["page"]== 'debug_area') {
wp_enqueue_media();
// Enqueue custom script that will interact with wp.media
wp_enqueue_script(
'myprefix_script',
plugins_url('/load_img.js', __FILE__),
array('jquery'),
'0.1');
}
});
// add ajax action to get the image async
add_action('wp_ajax_get_image_from_media_lib', function () {
if (isset($_GET['id'])) {
$image = wp_get_attachment_image(
filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT),
'medium',
false,
array('id' => 'image_preview')
);
$data = array(
'image' => $image,
);
wp_send_json_success($data);
} else {
wp_send_json_error();
}
});
2- add file JS that already included in enqueue
// load_img.js
jQuery(document).ready(_ => {
console.clear();
/**
* Define media_lib_frame as wp.media object
*/
const media_lib_frame = wp.media({
title: 'Select Media',
multiple: false,
library: {
type: 'image',
}
});
/**
* On close, get selections and save to the hidden input
* plus other AJAX stuff to refresh the image preview
*/
media_lib_frame.on('close', _ => {
const selection = media_lib_frame.state().get('selection');
const gallery_ids = selection.map(attachment => attachment['id']);
const ids = gallery_ids.join(",");
jQuery('input#idImage').val(ids);
loadImage(ids);
});
/**
* On open, get the id from the hidden input
* and select the appropriate images in the media manager
*/
media_lib_frame.on('open', _ => {
const selection = media_lib_frame.state().get('selection');
const ids = jQuery('input#idImage').val().split(',');
ids.forEach(id => {
const attachment = wp.media.attachment(id);
attachment.fetch();
selection.add(attachment ? [attachment] : []);
});
});
jQuery('button#btnOpenMediaLibFrame').click(e => {
e.preventDefault();
media_lib_frame.open();
});
});
// Ajax request to refresh the image preview
const loadImage = the_id => {
const data = {action: 'get_image_from_media_lib', id: the_id};
jQuery.get(ajaxurl, data, response => {
if (response.success === true) {
jQuery('#image_preview').replaceWith(response.data.image);
}
});
}
3- add this HTML into the function that responsible for render view
<img id="image_preview"/>
<input
type="hidden"
id="idImage"
class="regular-text"/>
<button
type='button'
class="button-primary"
id="btnOpenMediaLibFrame">
Select a image
</button>
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.
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);
...
});