WordPress

Add Upload Media To Library On Widgets

The WordPress media library is one of my favourite features in using WordPress over other CMS's, when you upload a new image into WordPress it will convert it to a number of a different sizes. These sizes can be defined in the settings -> media page, it will list three different image types where you can define new sizes for these image types.

These means that every image you upload will be converted into 4 different images, the original image, large, medium and thumbnail sizes, allowing you to put a high quality image in any position of your site.

By default the media library is only available straight from the main menu of WordPress or from a post edit page. The problem comes when you want to add the this same functionality into different places such as on a theme options or on the widget admin screen.

In this tutorial we are going to create a widget that has a field to add an image URL with an image you upload directly in the media library. This will also allow you to select a image from the media library that you've previously uploaded.

media-upload

First we start off by creating a new plugin which will be our widget, when the plugin is activated it will register the new widget on the widget_init action.

<?php
/*
* Plugin Name: Media Upload Widget
* Plugin URI: http://www.paulund.co.uk
* Description: A widget that allows you to upload media from a widget
* Version: 1.0
* Author: Paul Underwood
* Author URI: http://www.paulund.co.uk
* License: GPL2

Copyright 2012  Paul Underwood

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License,
version 2, as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
*/
/**
 * Register the Widget
 */
add_action( 'widgets_init', create_function( '', 'register_widget("pu_media_upload_widget");' ) );
[/php]
This will search for a class called <strong>pu_media_upload_widget</strong> and instantiate the class, so we will need to create a new class named <strong>pu_media_upload_widget</strong>. As we want this to be used as a widget you also need to extend the <strong>WordPress WP_Widget class</strong>, this comes with three methods that you need to override to use the widget.

The methods that you need to override are widget, update and form. The widget method is used to display the widget on the front-end, update method is used to add validation to the values from the admin form, the form method is the HTML to create the form in the admin area.

When creating a new widget you should try using the <a href="http://www.paulund.co.uk/wordpress-widget-boilerplate" title="WordPress Widget Boilerplate" target="_blank">Widget boilerplate</a> to get you started.

[php]
class pu_media_upload_widget extends WP_Widget
{
    /**
     * Constructor
     **/
    public function __construct()
    {
        $widget_ops = array(
            'classname' => 'pu_media_upload',
            'description' => 'Widget that uses the built in Media library.'
        );

        parent::__construct( 'pu_media_upload', 'Media Upload Widget', $widget_ops );
    }

    /**
     * Outputs the HTML for this widget.
     *
     * @param array  An array of standard parameters for widgets in this theme
     * @param array  An array of settings for this widget instance
     * @return void Echoes it's output
     **/
    public function widget( $args, $instance )
    {
        // Add any html to output the image in the $instance array
    }

    /**
     * Deals with the settings when they are saved by the admin. Here is
     * where any validation should be dealt with.
     *
     * @param array  An array of new settings as submitted by the admin
     * @param array  An array of the previous settings
     * @return array The validated and (if necessary) amended settings
     **/
    public function update( $new_instance, $old_instance ) 
    {

    }

    /**
     * Displays the form for this widget on the Widgets page of the WP Admin area.
     *
     * @param array  An array of the current settings for this widget
     * @return void
     **/
    public function form( $instance )
    {
       
    }
}

In the constructor of the widget we need to define the settings for WordPress to understand what to do with this widget code, this is done by calling the parent constructor with settings to register the widget.

The constructor is also a good place to assign any stylesheets or javascript that we need to add to the admin area to use the media library. Because we are going to use the default WordPress scripts and styles the files we need are already registered with WordPress we just need to enqueue them correctly. The Javascript files we need to load are media-upload and thickbox, which is the javascript for the pop-up boxes in the admin area. We will also need to make sure that we have loaded the styles for the thickbox dialog boxes.

/**
     * Constructor
     **/
    public function __construct()
    {
        $widget_ops = array(
            'classname' => 'pu_media_upload',
            'description' => 'Widget that uses the built in Media library.'
        );

        parent::__construct( 'pu_media_upload', 'Media Upload Widget', $widget_ops );

        add_action('admin_enqueue_scripts', array($this, 'upload_scripts'));
    }

    /**
     * Upload the Javascripts for the media uploader
     */
    public function upload_scripts()
    {
        wp_enqueue_script('media-upload');
        wp_enqueue_script('thickbox');
        wp_enqueue_script('upload_media_widget', plugin_dir_url(__FILE__) . 'upload-media.js', array('jquery'));

        wp_enqueue_style('thickbox');
    }

As you can see in the upload_scripts() method we have also defined a Javascript file called upload-media.js. This will be used to tell WordPress what button will load the media upload box and how to get the image URL back into the Widget textbox to save in the Widget data.

Javascript Code

The following code is what we will add into the upload-media.js file.

As you can see we are going to set a click event on the upload_image_button class, because we need to know what textbox to put the URL of the image in we are going to store this textbox element in a jQuery data variable.

Then we setup a function to tell WordPress what to do with the image information when it gets sent back from the media library iframe. This will take the image URL and add this into the textbox value that we stored in the jQuery data variable, then we will close the media upload window.

The next part of this function is the code to display the media upload box on the screen, this will simply open a thickbox dialog with an iframe of the media-upload.php file, which allows us to upload new images.

jQuery(document).ready(function($) {
    $(document).on("click", ".upload_image_button", function() {

        jQuery.data(document.body, 'prevElement', $(this).prev());

        window.send_to_editor = function(html) {
            var imgurl = jQuery(html).attr('src');
            var inputText = jQuery.data(document.body, 'prevElement');

            if(inputText != undefined && inputText != '')
            {
                inputText.val(imgurl);
            }

            tb_remove();
        };

        tb_show('', 'media-upload.php?type=image&TB_iframe=true');
        return false;
    });
});

The above code will allow us to click on our upload button to display a thickbox dialog of the media upload, like the following image.

media-library

With the Widget setup and the Javascript in place for uploading files we can add the HTML in the form() method to activate the Javascript to upload the images.

All we need for this is a title for the widget, a textbox for the image url and a button to open the thickbox dialog box. One thing you need to remember is to add the HTML class of upload_image_button to the button as this is the selector we assigned the click event to open the thickbox.

/**
     * Displays the form for this widget on the Widgets page of the WP Admin area.
     *
     * @param array  An array of the current settings for this widget
     * @return void
     **/
    public function form( $instance )
    {
        $title = __('Widget Image');
        if(isset($instance['title']))
        {
            $title = $instance['title'];
        }

        $image = '';
        if(isset($instance['image']))
        {
            $image = $instance['image'];
        }
        ?>
        <p>
            <label for="<?php echo $this->get_field_name( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
            <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
        </p>

        <p>
            <label for="<?php echo $this->get_field_name( 'image' ); ?>"><?php _e( 'Image:' ); ?></label>
            <input name="<?php echo $this->get_field_name( 'image' ); ?>" id="<?php echo $this->get_field_id( 'image' ); ?>" class="widefat" type="text" size="36"  value="<?php echo esc_url( $image ); ?>" />
            <input class="upload_image_button button button-primary" type="button" value="Upload Image" />
        </p>
    <?php
    }

Now when you click on the upload image button you should see the media library pop up in an iframe. This is a really good way for your users to select or upload images from the widget screen. If you think you have missed a step below is the full code for the widget.

Full WordPress Plugin

<?php
/*
* Plugin Name: Media Upload Widget
* Plugin URI: http://www.paulund.co.uk
* Description: A widget that allows you to upload media from a widget
* Version: 1.0
* Author: Paul Underwood
* Author URI: http://www.paulund.co.uk
* License: GPL2

Copyright 2012  Paul Underwood

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License,
version 2, as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
*/
/**
 * Register the Widget
 */
add_action( 'widgets_init', create_function( '', 'register_widget("pu_media_upload_widget");' ) );

class pu_media_upload_widget extends WP_Widget
{
    /**
     * Constructor
     **/
    public function __construct()
    {
        $widget_ops = array(
            'classname' => 'pu_media_upload',
            'description' => 'Widget that uses the built in Media library.'
        );

        parent::__construct( 'pu_media_upload', 'Media Upload Widget', $widget_ops );

        add_action('admin_enqueue_scripts', array($this, 'upload_scripts'));
    }

    /**
     * Upload the Javascripts for the media uploader
     */
    public function upload_scripts()
    {
        wp_enqueue_script('media-upload');
        wp_enqueue_script('thickbox');
        wp_enqueue_script('upload_media_widget', plugin_dir_url(__FILE__) . 'upload-media.js', array('jquery'));

        wp_enqueue_style('thickbox');
    }

    /**
     * Outputs the HTML for this widget.
     *
     * @param array  An array of standard parameters for widgets in this theme
     * @param array  An array of settings for this widget instance
     * @return void Echoes it's output
     **/
    public function widget( $args, $instance )
    {
        // Add any html to output the image in the $instance array
    }

    /**
     * Deals with the settings when they are saved by the admin. Here is
     * where any validation should be dealt with.
     *
     * @param array  An array of new settings as submitted by the admin
     * @param array  An array of the previous settings
     * @return array The validated and (if necessary) amended settings
     **/
    public function update( $new_instance, $old_instance ) {

        // update logic goes here
        $updated_instance = $new_instance;
        return $updated_instance;
    }

    /**
     * Displays the form for this widget on the Widgets page of the WP Admin area.
     *
     * @param array  An array of the current settings for this widget
     * @return void
     **/
    public function form( $instance )
    {
        $title = __('Widget Image');
        if(isset($instance['title']))
        {
            $title = $instance['title'];
        }

        $image = '';
        if(isset($instance['image']))
        {
            $image = $instance['image'];
        }
        ?>
        <p>
            <label for="<?php echo $this->get_field_name( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
            <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
        </p>

        <p>
            <label for="<?php echo $this->get_field_name( 'image' ); ?>"><?php _e( 'Image:' ); ?></label>
            <input name="<?php echo $this->get_field_name( 'image' ); ?>" id="<?php echo $this->get_field_id( 'image' ); ?>" class="widefat" type="text" size="36"  value="<?php echo esc_url( $image ); ?>" />
            <input class="upload_image_button" type="button" value="Upload Image" />
        </p>
    <?php
    }
}
?>
Back to top

Comments

  1. Paul says:

    Hey,

    Thanks for this article, just what I was looking for and it works like a charm!

    Would it be possible to take advantage of the new responsive images (srcset/sizes) using this plugin?

    If possible, would you be able to point me in the right direction?

    Would be a great addition to this plugin.

    Thanks again.

    Paul

  2. Spencer Bigum says:

    I had to change some javascript to get this working:

    var imgurl = jQuery(html).find('img').attr('src');

    I had to target the image itself - incase anyone else needs this. Great job on the post for sure!

  3. Maz says:

    Amazing tutorial thanks!!! I was wondering though how to take it one step further and actually dispay the uploaded image inside the widget on the front end. I have tried doing this:

    public function widget( $args, $instance )
    {
    ?>

    <img src=" " /> <?php
    }

    When I replace $id with an actual id (say 13 for example) then I get the image displayed in the widget on the front end but the id can't be hardcoded. Do you have any pointers as to how to reference the attachement id in this plugin?

    Many Thanks

    Maz