0

I've created a custom Wordpress widget that allows me to upload images with the media uploader, and all is working fine but now I'd like to make it repeatable. I'm using it to upload photos for a simple slider, which is why I need to have multiple media uploaders within the one widget. It won't work to just allow the one media uploader to select multiple photos because I have text fields to go with each specific photo.

Ideally it would be nice to have some sort of "Add another slide" button to allow me to have as many uploaders as I want within the one widget, but at this point of would settle for having to set a certain number of slides in the code.

I've never done anything like this before, so this code is just purely bits that I've put together from what I've found with online searches, which means I don't understand it terribly well so I haven't been able to figure out how to make it repeat. I've messed around with some different things, but haven't been able to get anything working. I've tried simply duplicating the image upload part of the code and changing the ID like I was able to do with the text areas, but that just gave me two media uploaders that seemed to be linked because when I would change one, they'd both change.

I'm also open to any suggestions on ways that this code may be improved or cleaned up. Like I said, I'm a bit out of my element with this so I'm not sure how well this code is written.

The PHP

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

<p>
    <label for="<?php echo $this->get_field_id('image_uri_1'); ?>">Image</label><br />
    <?php
        if ( $instance['image_uri_1'] != '' ) :
            echo '<img class="custom_media_image" src="' . $instance['image_uri_1'] . '" 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_1'); ?>" id="<?php echo $this->get_field_id('image_uri_1'); ?>" value="<?php echo $instance['image_uri_1']; ?>" 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_1'); ?>" value="Upload Image" style="margin-top:5px;" />
</p>

The JS

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');
});

Thanks in advance!

0

Naive repeatable are impossible with widgets as the data structure and UI tend to be rigid. On the face of it, the way you describe it in the question, you can just use the media library to select multiple images instead of one, and keep them as a list of attachment IDs. You should take a look at the core gallery image for inspiration.

If this is not good enough, the way to go is to separate between the UI and the DB storage of the widget data. Just following the same line of thought presented in the gallery widget, instead of having a field per repeatable data you group all the data into one hidden input field and create a JS that exctracts the data out of it when the widget form is displayed, and stores the data in it once there is a change. (obviously if one storage "field" feels too restrictive, you can use more, the point is to have a constant number of them)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.