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="#" rel="nofollow noreferrer noopener"><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.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

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

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


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x