Create Image Uploader for Widget

I found this post//

Use Media upload in custom widget on wordpress 3.5

I’m not experienced in any of this so I pretty much just copied the code he provided into my own functions.php file. I uploaded the JS and everything…

I then replaced certain code that “sven” posted in his answer.

The uploader works perfectly but when I view front end the image isn’t even displayed…

Here is the code within my functions.php//

(it includes the registered sidebars and the custom widget etc)

 if (function_exists('register_sidebar')) {
 register_sidebar(array(
  'name' => 'Left Sidebar',
  'id'   => 'left-sidebar',
  'description'   => 'Widget Area',
  'before_widget' => '<div id="one" class="two"><h1>EOTW//</h1>',
  'after_widget'  => '</div>',
  'before_title'  => '<h2>',
  'after_title'   => '</h2>'
 ));
}


add_action('widgets_init', 'ctUp_ads_widget');
function ctUp_ads_widget() {
register_widget( 'ctUp_ads' );
}

function ctUp_wdScript(){
wp_enqueue_media();
wp_enqueue_script('adsScript', get_template_directory_uri() . '/js/ads.js');
}
add_action('admin_enqueue_scripts', 'ctUp_wdScript');

class ctUp_ads extends WP_Widget{

function ctUp_ads() {
    $widget_ops = array( 'classname' => 'ctUp-ads' );
    $control_ops = array( 'width' => 250, 'height' => 350, 'id_base' => 'ctUp-ads-widget' );
    $this->WP_Widget( 'ctUp-ads-widget','EOTW', $widget_ops, $control_ops );
}

public function widget($args, $instance){ 
    extract( $args );   
?>
<a href="#"><img src="<?php echo esc_url($instance['image_uri']); ?>" /></a>
<?php }

function update($new_instance, $old_instance) {
    $instance = $old_instance;
    $instance['text'] = strip_tags( $new_instance['text'] );
    $instance['image_uri'] = strip_tags( $new_instance['image_uri'] );
    return $instance;
}

public function form($instance){ ?>
<p>
  <label for="<?php echo $this->get_field_id('text'); ?>"><?php _e('Text', 'themename'); ?></label><br />
  <input type="text" name="<?php echo $this->get_field_name('text'); ?>" id="<?php echo $this->get_field_id('text'); ?>" value="<?php echo $instance['text']; ?>" class="widefat" />
</p>
<p>
  <label for="<?php echo $this->get_field_id('image_uri'); ?>">Image</label><br />
    <img class="custom_media_image" src="<?php if(!empty($instance['image_uri'])){echo $instance['image_uri'];} ?>" style="margin:0;padding:0;max-width:100px;float:left;display:inline-block" />
    <input type="text" class="widefat custom_media_url" name="<?php echo $this->get_field_name('image_uri'); ?>" id="<?php echo $this->get_field_id('image_uri'); ?>" value="<?php echo $instance['image_uri']; ?>">
    <input type="button" value="<?php _e( 'Upload Image', 'themename' ); ?>" class="button custom_media_upload" id="custom_image_uploader"/>
</p>
<?php } }  ?>

Here is the JS//

jQuery(document).ready( function(){
function media_upload( button_class) {
var _custom_media = true,
_orig_send_attachment = wp.media.editor.send.attachment;
jQuery('body').on('click',button_class, function(e) {
    var button_id ='#'+jQuery(this).attr('id');
    /* console.log(button_id); */
    var self = jQuery(button_id);
    var send_attachment_bkp = wp.media.editor.send.attachment;
    var button = jQuery(button_id);
    var id = button.attr('id').replace('_button', '');
    _custom_media = true;
    wp.media.editor.send.attachment = function(props, attachment){
        if ( _custom_media  ) {
           jQuery('.custom_media_id').val(attachment.id); 
           jQuery('.custom_media_url').val(attachment.url);
               jQuery('.custom_media_image').attr('src',attachment.url).css('display','block');   
        } else {
            return _orig_send_attachment.apply( button_id, [props, attachment] );
        }
    }
    wp.media.editor.open(button);
    return false;
});
}
media_upload( '.custom_media_upload');
});

Now my question is, what exactly do I have to fix in order for this image uploader to work?
I figured the updates “sven” provided would help but clearly I am missing something.
Please Help.

Solutions Collecting From Web of "Create Image Uploader for Widget"

Okay, I re-checked the code and everything is fine! (Sorry for my misleading comment!)

While testing I tweaked the code a little bit, but you can also keep on using your version.

But let’s face it in detail: the registered sidebar (with the ID left-sidebar) has two arguments to wrap the whole widget (before_widget and after_widget) which you can output via echo $before_widget and echo $after_widget in your widget (see my version below).

The next two arguments (before_title and after_title) are not defined in your widget, but I added the filter to the text-field so you can get the idea:

<?php
// register sidebar
if (function_exists('register_sidebar')) {
    register_sidebar(
        array(
        'name' => 'Left Sidebar',
        'id' => 'left-sidebar',
        'description' => 'Widget Area',
        'before_widget' => '<div id="one" class="two">',
        'after_widget' => '</div>',
        )
    );
}

// register widget
add_action('widgets_init', 'ctUp_ads_widget');
function ctUp_ads_widget() {
    register_widget( 'ctUp_ads' );
}

// add admin scripts
add_action('admin_enqueue_scripts', 'ctup_wdscript');
function ctup_wdscript() {
    wp_enqueue_media();
    wp_enqueue_script('ads_script', get_template_directory_uri() . '/js/widget.js', false, '1.0', true);
}

// widget class
class ctUp_ads extends WP_Widget {

    function ctUp_ads() {
        $widget_ops = array('classname' => 'ctUp-ads');
        $this->WP_Widget('ctUp-ads-widget', 'EOTW', $widget_ops);
    }

    function widget($args, $instance) {
        extract($args);

        // widget content
        echo $before_widget;
?>

    <h1><?php echo apply_filters('widget_title', $instance['text'] ); ?></h1>
    <a href="#">
        <img src="<?php echo esc_url($instance['image_uri']); ?>" />
    </a>

<?php
        echo $after_widget;

    }

    function update($new_instance, $old_instance) {
        $instance = $old_instance;
        $instance['text'] = strip_tags( $new_instance['text'] );
        $instance['image_uri'] = strip_tags( $new_instance['image_uri'] );
        return $instance;
    }

    function form($instance) {
?>

    <p>
        <label for="<?php echo $this->get_field_id('text'); ?>">Text</label><br />
        <input type="text" name="<?php echo $this->get_field_name('text'); ?>" id="<?php echo $this->get_field_id('text'); ?>" value="<?php echo $instance['text']; ?>" class="widefat" />
    </p>
    <p>
        <label for="<?php echo $this->get_field_id('image_uri'); ?>">Image</label><br />

        <?php
            if ( $instance['image_uri'] != '' ) :
                echo '<img class="custom_media_image" src="' . $instance['image_uri'] . '" style="margin:0;padding:0;max-width:100px;float:left;display:inline-block" /><br />';
            endif;
        ?>

        <input type="text" class="widefat custom_media_url" name="<?php echo $this->get_field_name('image_uri'); ?>" id="<?php echo $this->get_field_id('image_uri'); ?>" value="<?php echo $instance['image_uri']; ?>" style="margin-top:5px;">

        <input type="button" class="button button-primary custom_media_button" id="custom_media_button" name="<?php echo $this->get_field_name('image_uri'); ?>" value="Upload Image" style="margin-top:5px;" />
    </p>

<?php
    }
}
?>

And the script:

jQuery(document).ready( function($) {
    function media_upload(button_class) {
        var _custom_media = true,
        _orig_send_attachment = wp.media.editor.send.attachment;

        $('body').on('click', button_class, function(e) {
            var button_id ='#'+$(this).attr('id');
            var self = $(button_id);
            var send_attachment_bkp = wp.media.editor.send.attachment;
            var button = $(button_id);
            var id = button.attr('id').replace('_button', '');
            _custom_media = true;
            wp.media.editor.send.attachment = function(props, attachment){
                if ( _custom_media  ) {
                    $('.custom_media_id').val(attachment.id);
                    $('.custom_media_url').val(attachment.url);
                    $('.custom_media_image').attr('src',attachment.url).css('display','block');
                } else {
                    return _orig_send_attachment.apply( button_id, [props, attachment] );
                }
            }
            wp.media.editor.open(button);
                return false;
        });
    }
    media_upload('.custom_media_button.button');
});

Your widget can now be part of every sidebar (aka widget area). To output an sidebar your can use the function dynamic_sidebar() which will work everywhere in your template:

<?php
    if ( is_active_sidebar( 'left-sidebar' ) ) :
        dynamic_sidebar('left-sidebar');
    endif;
?>

Note: There might be a minor problem if you’re using this widget in more than one sidebar! (…because every widget will have the same ID which will cause the script to update each image.) Fortunately this is not as bad as it sounds because if you hit the safe-button only the current one will be safed to the database 🙂

I got Svens answer to work but like he said at the end, there is an issue with ids and if you have multiple uploaders on one page is will change all them at once, i started to run into problems when I was usuing this for widgets in page composers and such. I fixed it by using the unique id from the widget.

My form code was this:

<label class="widg-label widg-img-label" for="<?php echo $this->get_field_id( 'image_uri' ); ?>">Image</label>
<div class="widg-img" >
    <img class="<?php echo $this->get_field_id( 'image_id' ); ?>_media_image custom_media_image" src="<?php if( !empty( $instance['image_uri'] ) ){echo $instance['image_uri'];} ?>" />
    <input input type="hidden" type="text" class="<?php echo $this->get_field_id( 'image_id' ); ?>_media_id custom_media_id" name="<?php echo $this->get_field_name( 'image_id' ); ?>" id="<?php echo $this->get_field_id( 'image_id' ); ?>" value="<?php echo $instance['image_id']; ?>" />
    <input type="text" class="<?php echo $this->get_field_id( 'image_id' ); ?>_media_url custom_media_url" name="<?php echo $this->get_field_name( 'image_uri' ); ?>" id="<?php echo $this->get_field_id( 'image_uri' ); ?>" value="<?php echo $instance['image_uri']; ?>" >
    <input type="button" value="Upload Image" class="button custom_media_upload" id="<?php echo $this->get_field_id( 'image_id' ); ?>"/>
</div>

and my js was:

jQuery(document ).ready( function(){
    function media_upload( button_class ) {
        var _custom_media = true,
            _orig_send_attachment = wp.media.editor.send.attachment;
         jQuery('body').on('click','.custom_media_upload',function(e) {
            var button_id ='#'+jQuery(this).attr( 'id' );
            var button_id_s = jQuery(this).attr( 'id' ); 
            console.log(button_id); 
            var self = jQuery(button_id);
            var send_attachment_bkp = wp.media.editor.send.attachment;
            var button = jQuery(button_id);
            var id = button.attr( 'id' ).replace( '_button', '' );
            _custom_media = true;

            wp.media.editor.send.attachment = function(props, attachment ){
                if ( _custom_media ) {
                    jQuery( '.' + button_id_s + '_media_id' ).val(attachment.id); 
                    jQuery( '.' + button_id_s + '_media_url' ).val(attachment.url);
                    jQuery( '.' + button_id_s + '_media_image' ).attr( 'src',attachment.url).css( 'display','block' ); 
                } else {
                    return _orig_send_attachment.apply( button_id, [props, attachment] );
                }
            }
            wp.media.editor.open(button);
            return false;
        });
    }
    media_upload( '.custom_media_upload' );

});

mainly just used my unique id in my widget form

<?php echo $this->get_field_id( 'image_id' ); ?>

and added that infront of the classes, then retrived it without the #,

var button_id_s = jQuery(this).attr( 'id' ); 

then inserted it before all the classes so they would match the form

   jQuery( '.' + button_id_s + '_media_id' ).val(attachment.id); 
                    jQuery( '.' + button_id_s + '_media_url' ).val(attachment.url);
                    jQuery( '.' + button_id_s + '_media_image' ).attr( 'src',attachment.url).css( 'display','block' );

Hope is helps someone who is having this same issue.