Using the WordPress 3.5 Media Uploader in Your Plugin or Theme

Back in 2010, I wrote a post on Using the WordPress Uploader in Your Plugin or Theme that went on to be one of my most popular tutorials of all time. Then the WordPress team went and added a much cooler media uploader in version 3.5 and make that post outdated. Since most of you probably want to add the new uploader in a theme or plugin you’re working on right now, I figured it was time for an updated post.

WordPress 3.5 Media Uploader

The process required to add the new uploader is a bit different, but not too much more difficult. I was able to adapt the old tutorial a little, so it shouldn’t be too hard to replace some code in an existing project and get the new uploader instead of the old.

For the sake of simplicity, let’s start with the same HTML snippet as in the old tutorial. This goes along with the rest of the HTML for your admin page, or wherever in the admin you’re trying to add an upload field.

<label for="upload_image">
	<input id="upload_image" type="text" size="36" name="ad_image" value="http://" /> 
	<input id="upload_image_button" class="button" type="button" value="Upload Image" />
	<br />Enter a URL or upload an image
</label>

Now we need to load up the necessary JavaScript files.

add_action('admin_enqueue_scripts', 'my_admin_scripts');

function my_admin_scripts() {
	if (isset($_GET['page']) && $_GET['page'] == 'my_plugin_page') {
		wp_enqueue_media();
		wp_register_script('my-admin-js', WP_PLUGIN_URL.'/my-plugin/my-admin.js', array('jquery'));
		wp_enqueue_script('my-admin-js');
	}
}

We bind the my_admin_scripts() function to the admin_enqueue_scripts hook, and enqueue both the media scripts and our own JavaScript file. Also, the scripts will only be loaded if the current page is equal to “my_plugin_page,” which you would of course replace with the slug your admin menu has.

Now for the complicated part: the script that hooks into the uploader. Continuing with the above example, it would be named my-admin.js.

jQuery(document).ready(function($){


	var custom_uploader;


	$('#upload_image_button').click(function(e) {

		e.preventDefault();

		//If the uploader object has already been created, reopen the dialog
		if (custom_uploader) {
			custom_uploader.open();
			return;
		}

		//Extend the wp.media object
		custom_uploader = 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
		custom_uploader.on('select', function() {
			attachment = custom_uploader.state().get('selection').first().toJSON();
			$('#upload_image').val(attachment.url);
		});

		//Open the uploader dialog
		custom_uploader.open();

	});


});

When the button is clicked, it creates a new instance of the wp.media object and configures it to only accept a single file, since the text field can only hold one file URL. Then it binds a function to the selection action, which gets the file attributes when an image is chosen and sets the #upload_image text field value to the file’s URL.

Providing everything went as expected, you should have a form field that will accept an arbitrary URL, or allow the user to upload one.

File Upload Field

10 Comments

  1. Thank you for this great tutorial! I was wondering if there is a similar way to add or customize the attachment editor dialog in posts and pages. It seems that when we add meta data at the upload stage then we attach the meta data to that specific attachment across all posts and pages, when in some cases it would be desirable to add meta data to an attachment on a post to post basis.

  2. Nathan

    Thanks for the tutorial as it is very useful and informative for WordPress users in general. I am definitely going to use it for my WordPress Viewer plugin by GroupDocs. It has proved to be a handy tool to view various file formats and WordPress new Uploader will make it more easy for me. Thanks again!

    http://groupdocs.com/blog/grou.....press.html

  3. Hey Matt,

    Thanks for the great post. This is one of the articles that was great help in moving forward for my project.

    However I’ve run into a strange problem when trying to display thumbnails of images I just uploaded:

    // Show Thumbs
    var attachment_thumbs = selection.map(function(attachment) {
    attachment = attachment.toJSON();
    console.log(‘sizes’, attachment);
    return ”;
    }).join(‘ ‘);
    $(‘#thumbs’).html(attachment_thumbs);

    When selecting images that were previously uploaded to the media gallery, this code works like a charm to display thumbnails as feedback to the user that their selection was successful (I’m doing front-end posting).

    The problem happens when I upload an image and select it right away (after waiting for upload to complete). The console log gives me an empty object:
    Object {id: “”, title: “”, caption: “”, description: “”}
    And I also get an error:
    Uncaught TypeError: Cannot read property ‘thumbnail’ of undefined

    I’ve tried waiting but that doesn’t help. The only thing that can force the media uploader to define the javascript image object completely seems to be selecting multiple other images (previously uploaded), using those, and then going back to the media uploader and picking the fresh images again.

    This seems very strange to me, and I can’t figure out where the source of the issue lies as the code behind the media uploader is compressed and far from transparent.

    • So it turns out that the media uploader often creates a first empty object… not sure why. I simply filtered out any empty objects and it works fine now.

  4. waqas

    Great tutorial. Thnk you. I have been trying to put this on the front-end, to give users the ability to upload an image, but nothing happens when i click upload image button, any tips? I would appreciate it

  5. Although I’m not that good at coding. I felt this will help me in configuring my blog.

    Kudos !

  6. How to get back a multiple attachment url into a for example!
    I’m not good at coding ><"!

    • When the button is clicked, it creates a new instance of the wp.media object and configures it to only accept a single file, since the text field can only hold one file URL. Then it binds a function to the selection action, which gets the file attributes when an image is chosen and sets the #upload_image text field value to the file’s URL.

  7. Matt,

    I noticed in the attachment object that the 3.5 Uploader returns, there is the attachment ID. I’m saving this, instead of the attachment URL, so that I can show thumbnails of these extra images in the admin section and on my CTP single page, and then fetch a larger image with AJAX based on the attachment ID:

    In my meta box:
    <input name="pr_product_image1_id" id="pr_product_image1_id" class="pr-attachment-id" type="hidden" value="” />

    In my Javascript click handler:
    $( ‘.img_button’ ).click( function( e ) {
    e.preventDefault();
    attachment_id_field = $( this ).prev( ‘.pr-attachment-id’ ).attr( ‘name’ );

    ( same code as Matt used…)

    //When a file is selected, grab the URL and set it as the text field’s value
    custom_uploader.on( ‘select’, function() {
    var attachment = custom_uploader.state().get(‘selection’).first().toJSON();
    $(‘#’+attachment_id_field).val(attachment.id);
    });
    //Open the uploader dialog
    custom_uploader.open();
    });

    This allows me to use “echo wp_get_attachment_image” to display the thumbnail in the metabox after the page is updated or when the user comes back to edit it later, but I’m still trying to figure out how to show the thumbnail immediately, as soon as the image is attached.

    Can anyone help?

Leave a Reply

*