Add inline uploader to plugin option page

Okay, here is what I came up with: It’s all about using the plupload library that comes shipped with WP.

1. Add a <div> to your plugin’s option page that later becomes the drag’n’drop area

    <div class="your-plugin-uploader multiple">
        <input id="your-plugin-uploader-button" type="button" value="<?php esc_attr_e( 'Select Files' ); ?>" class="your-plugin-uploader-button button">
        <span class="ajaxnonce" id="<?php echo wp_create_nonce( __FILE__ ); ?>"></span>
    </div>

2. Register your plugin JS and make sure you define plupload-all as a dependency for your script

    function se179618_admin_js() {
        wp_register_script( 'your-plugin', WP_PLUGIN_URL . '/your-plugin/js/your-plugin.js', array( 'jquery', 'plupload-all' ) );
    }
    add_action( 'admin_enqueue_scripts', 'se179618_admin_js' );

3. Write some plupload settings to the page’s <head>

    function se179618_admin_head() {
        $uploader_options = array(
            'runtimes'          => 'html5,silverlight,flash,html4',
            'browse_button'     => 'my-plugin-uploader-button', 
            'container'         => 'my-plugin-uploader', 
            'drop_element'      => 'my-plugin-uploader', 
            'file_data_name'    => 'async-upload', 
            'multiple_queues'   => true,
            'max_file_size'     => wp_max_upload_size() . 'b',
            'url'               => admin_url( 'admin-ajax.php' ),
            'flash_swf_url'     => includes_url( 'js/plupload/plupload.flash.swf' ),
            'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
            'filters'           => array( 
               array( 
                  'title' => __( 'Allowed Files' ), 
                  'extensions' => '*'
               ) 
            ),
            'multipart'         => true,
            'urlstream_upload'  => true,
            'multi_selection'   => true, 
            'multipart_params' => array(
                '_ajax_nonce' => '',            
                'action'      => 'my-plugin-upload-action'          
            )
        );
    ?>
    <script type="text/javascript">
        var global_uploader_options=<?php echo json_encode( $uploader_options ); ?>;
    </script>
    <?php
    }
    add_action( 'admin_head', 'se179618_admin_head' );

4. Add the action called by the AJAX uploader

    function se179618_ajax_action() {
        // check ajax nonce
        check_ajax_referer( __FILE__ );

        if( current_user_can( 'upload_files' ) ) {
            $response = array();

            // handle file upload
            $id = media_handle_upload( 
               'async-upload',
               0, 
               array( 
                  'test_form' => true, 
                  'action' => 'my-plugin-upload-action' 
               )
            );

            // send the file' url as response
            if( is_wp_error( $id ) ) {
                $response['status'] = 'error';
                $response['error'] = $id->get_error_messages();
            } else {
                $response['status'] = 'success';

                $src = wp_get_attachment_image_src( $id, 'thumbnail' );
                $response['attachment'] = array();
                $response['attachment']['id'] = $id;
                $response['attachment']['src'] = $src[0];
            }

        }

        echo json_encode( $response );
        exit;
    }

    add_action( 'wp_ajax_my-plugin-upload-action', 'se179618_ajax_action' ); 

5. Initiate the uploader in your plugin’s JS

    jQuery( document ).ready( function() {

        if( jQuery( '.your-plugin-uploader' ).length > 0 ) {
            var options = false;
            var container = jQuery( '.your-plugin-uploader' );
            options = JSON.parse( JSON.stringify( global_uploader_options ) );
            options['multipart_params']['_ajax_nonce'] = container.find( '.ajaxnonce' ).attr( 'id' );

            if( container.hasClass( 'multiple' ) ) {
                  options['multi_selection'] = true;
             }

            var uploader = new plupload.Uploader( options );
            uploader.init();

            // EVENTS
            // init
            uploader.bind( 'Init', function( up ) {
                console.log( 'Init', up );
            } );

            // file added
            uploader.bind( 'FilesAdded', function( up, files ) {
                jQuery.each( files, function( i, file ) {
                    console.log( 'File Added', i, file );
                } );

               up.refresh();
               up.start();
            } );

            // upload progress
            uploader.bind( 'UploadProgress', function( up, file ) {
                console.log( 'Progress', up, file )
            } );

            // file uploaded
            uploader.bind( 'FileUploaded', function( up, file, response ) {
                response = jQuery.parseJSON( response.response );

                if( response['status'] == 'success' ) {
                    console.log( 'Success', up, file, response );
                } else {
                    console.log( 'Error', up, file, response );
                }

            } );
        }

    } );

Leave a Comment