Crear Cargador de Imágenes para Widget
Encontré esta publicación//
Usar carga de medios en widget personalizado en WordPress 3.5
No tengo experiencia en nada de esto, así que básicamente copié el código que proporcionó en mi archivo functions.php. Subí el JS y todo...
Luego reemplacé cierto código que "sven" publicó en su respuesta.
El cargador funciona perfectamente pero cuando veo el frontend la imagen ni siquiera se muestra...
Aquí está el código dentro de mi functions.php//
(incluye las barras laterales registradas y el widget personalizado, etc)
if (function_exists('register_sidebar')) {
register_sidebar(array(
'name' => 'Barra lateral izquierda',
'id' => 'left-sidebar',
'description' => 'Área de Widget',
'before_widget' => '<div id="one" class="two"><h1>EOTW//</h1>',
'after_widget' => '</div>',
'before_title' => '<h2>',
'after_title' => '</h2>'
));
}
// Registrar el widget
add_action('widgets_init', 'ctUp_ads_widget');
function ctUp_ads_widget() {
register_widget( 'ctUp_ads' );
}
// Cargar scripts necesarios
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('Texto', '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'); ?>">Imagen</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( 'Subir Imagen', 'themename' ); ?>" class="button custom_media_upload" id="custom_image_uploader"/>
</p>
<?php } } ?>
Aquí está el 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');
});
Ahora mi pregunta es, ¿qué tengo que arreglar exactamente para que este cargador de imágenes funcione? Pensé que las actualizaciones que proporcionó "sven" ayudarían, pero claramente me estoy perdiendo algo. Por favor ayuda.

Analicemos esto en detalle: La barra lateral registrada (con el ID left-sidebar
) tiene dos argumentos para envolver todo el widget (before_widget
y after_widget
) que puedes mostrar mediante echo $before_widget
y echo $after_widget
en tu widget (ver mi versión a continuación):
<?php
// Registrar barra lateral
if (function_exists('register_sidebar')) {
register_sidebar(
array(
'name' => 'Barra lateral izquierda',
'id' => 'left-sidebar',
'description' => 'Área de widgets',
'before_widget' => '<div id="one" class="two">',
'after_widget' => '</div>',
)
);
}
// Registrar widget
add_action('widgets_init', 'ctUp_ads_widget');
function ctUp_ads_widget() {
register_widget( 'ctUp_ads' );
}
// Cargar scripts adicionales en el admin
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'); ?>">Texto</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' ); ?>">Imagen</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="Subir imagen" style="margin-top:5px;" />
</p>
<?php
}
}
Y el JavaScript para el botón de subida:
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');
});
Ahora tu widget puede ser parte de cualquier barra lateral (también conocida como área de widgets). Para mostrar una barra lateral puedes usar la función dynamic_sidebar()
que funcionará en cualquier parte de tus plantillas:
if ( is_active_sidebar('left-sidebar') ) {
dynamic_sidebar('left-sidebar');
}
Actualización 01/2019: He ajustado el código para que funcione con múltiples widgets y barras laterales.

¡Muchas gracias por tu ayuda! ¡Funciona perfectamente! Realmente aprecio tu amabilidad.

Muchas gracias, pero en mi widget el archivo de carga solo se actualiza cuando cambio algo dentro del campo URL o en un campo diferente. La subida de imágenes no actualiza este campo, ¿puedes ayudarme?

Logré que la respuesta de Svens funcionara pero como él mencionó al final, hay un problema con los IDs y si tienes múltiples cargadores en una página, cambiará todos a la vez. Comencé a tener problemas cuando usaba esto para widgets en constructores de páginas y similares. Lo solucioné utilizando el ID único del widget.
Mi código del formulario era este:
<label class="widg-label widg-img-label" for="<?php echo $this->get_field_id( 'image_uri' ); ?>">Imagen</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="Subir imagen" class="button custom_media_upload" id="<?php echo $this->get_field_id( 'image_id' ); ?>"/>
</div>
y mi JavaScript era:
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');
});
Principalmente usé mi ID único en mi formulario de widget
<?php echo $this->get_field_id('image_id'); ?>
y lo agregué delante de las clases, luego lo recuperé sin el #,
var button_id_s = jQuery(this).attr('id');
luego lo inserté antes de todas las clases para que coincidieran con el formulario
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');
Espero que esto ayude a alguien que tenga el mismo problema.
