Create Image Uploader for Widget

I found this post//

Use Media upload in custom widget on wordpress 3.5

Read More

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.

Related posts

2 comments

  1. 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):

    <?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' );
    }
    
    // Enqueue additional 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.0', true);
    }
    
    // Widget
    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) {
            echo $before_widget;
    ?>
    
        <h1><?php echo apply_filters('widget_title', $instance['text'] ); ?></h1>
        <img src="<?php echo esc_url($instance['image_uri']); ?>" />
    
    <?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="<?= $this->get_field_id( 'image_uri' ); ?>">Image</label>
            <img class="<?= $this->id ?>_img" src="<?= (!empty($instance['image_uri'])) ? $instance['image_uri'] : ''; ?>" style="margin:0;padding:0;max-width:100%;display:block"/>
            <input type="text" class="widefat <?= $this->id ?>_url" name="<?= $this->get_field_name( 'image_uri' ); ?>" value="<?= $instance['image_uri'] ?? ''; ?>" style="margin-top:5px;" />
            <input type="button" id="<?= $this->id ?>" class="button button-primary js_custom_upload_media" value="Upload Image" style="margin-top:5px;" />
        </p>
    
    <?php
        }
    }
    

    And the JavaScript for the upload button:

    jQuery(document).ready(function ($) {
      function media_upload(button_selector) {
        var _custom_media = true,
            _orig_send_attachment = wp.media.editor.send.attachment;
        $('body').on('click', button_selector, function () {
          var button_id = $(this).attr('id');
          wp.media.editor.send.attachment = function (props, attachment) {
            if (_custom_media) {
              $('.' + button_id + '_img').attr('src', attachment.url);
              $('.' + button_id + '_url').val(attachment.url);
            } else {
              return _orig_send_attachment.apply($('#' + button_id), [props, attachment]);
            }
          }
          wp.media.editor.open($('#' + button_id));
          return false;
        });
      }
      media_upload('.js_custom_upload_media');
    });
    

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

    if ( is_active_sidebar('left-sidebar') ) {
        dynamic_sidebar('left-sidebar');
    }
    

    Update 01/2019: I tweaked the code to make it work with multiple widgets and sidebars.

  2. 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.

Comments are closed.