6

My jQuery script works just fine for opening the wp.media uploader, selecting or uploading a single image, and both displaying the image and adding its attachment ID to an existing options array via hidden input (on my plugins settings page). My objective is to re-produce the identical results, but for multiple images at a time.

Like many before me, I have hit a block on using wp.media for such purposes.

First, I'll present the full working script: It opens the media frame, allows me to select an image, captures the image attachment ID for the hidden input (the most crucial function) and also happens to provide a preview image prior to a save action that, on page refresh, displays the image via its attachment ID just where I want it. Most of it will be familiar to anyone who has researched and written routines for using wp.media, and this particular usage (setting aside peculiarities of my plugin's set-up) is well-documented by now, at least in comparison to multiple files usage.

WORKING SINGLE IMAGE CODE

jQuery(document).ready( function($) {

    var myplugin_media_upload;

    $('#myplugin-change-image').click(function(e) {
        e.preventDefault();

    // If the uploader object has already been created, reopen the dialog
        if( myplugin_media_upload ) {
            myplugin_media_upload.open();
            return;
        }

    // Extend the wp.media object
        myplugin_media_upload = wp.media.frames.file_frame = wp.media({
            title: button_text.title,
            button: { text: button_text.button },
            multiple: false
        });

    //When a file is selected, grab the URL and set it as the text field's value
        myplugin_media_upload.on( 'select', function() {
            attachment = myplugin_media_upload.state().get( 
                 'selection' ).first().toJSON();
            console.log(attachment); //irrelevant to functionality but useful
            //adds the ID to the hidden input
            $('#myplugin-featured-image').val( attachment.id );
            //provides the preview image
            $('#myplugin-thumbnail').empty();
            $('#myplugin-thumbnail').append( 
                '<img src="' + attachment.url + 
                '" class="attachment-thumbnail myplugin-preview" />' );
            $('#myplugin-new-global').show();
        });

    //Open the uploader dialog
        myplugin_media_upload.open();
    });

});

MOSTLY DYSFUNCTIONAL MULTIPLE IMAGES ATTEMPT

Combining snippets of multiple selection routines from here and there, I tried various adaptations. The following segment from one such try focuses on the key sequence. I present it not because it had a ghost of a chance of being completely successful, but because it is partly successful and does yield some possibly useful and interesting info:

// Extend the wp.media object
    myplugin_media_upload = wp.media.frames.file_frame = wp.media({
        title: button_text.title,
        button: { text: button_text.button },
        multiple: true //get multiple images
    });

//When a file is selected, grab the URL and set it as the text field's value
    myplugin_media_upload.on( 'select', function() {
        var selection = myplugin_media_upload.state().get( 'selection' );
        selection.map( function( attachment ) {
            attachment.toJSON();

            //shows each attachment ID:
            console.log(attachment.id);
            //last is captured for:
            $('#myplugin-featured-image').val( attachment.id );

            //captures code fragment (see notes)
            console.log(attachment.url);

        });

    });

Though the last, "attachment-thumbnail"-related stuff from the prior example doesn't work at all, so hasn't been included, this code DOES capture the last attachment ID of however many images were selected, and appends it as the needed "val" for the hidden input.

Looking at the console, I find that however many images selected are in fact collected, ID by ID. However, attachment.url turns out to register as a snippet of dysfunctional URL-deriving code apparently from wp-includes/js/backbone.min.js. Maybe someone will find a clue here, or at least find it a little amusing (!?).

I think I want to capture the IDs as they are exposed, assemble them in an array, and foreach-loop them into a different type of image display, probably with incremented html IDs, and I likewise need to be able to capture the array for PHP processing.

I'm pretty sure I could handle the last two parts (display and PHP processing) once the "assemble and access array" parts were handled, but at this point my facility with jQuery becomes woefully inadequate. It's led to hours of bad trial and error, with lots of "undefined" notices when I try to access variables that I think really ought to be arrays of IDs. So far nothing that I have tried has done much more than decorate the console and at best give me one usable value as already described.

I'm hoping that someone can provide an answer that, in addition to solving this particular problem, will amount to a working template for getting and using multiple image selection in plug-ins, themes, and functions.

PPS: Hold the Phone I think I've almost got an answer, shockingly enough.

Though I'd still be curious to see what a real jQuery master came up with... ;)

1 Answer 1

9

So, this works. I'd be happy to implement and credit improvements!

/**
 * @Script: WordPress Multiple Image Selection in jQuery
 * @Version: 0.1
 * @Author: CK MacLeod
 * @Author URI: http://ckmacleod.com
 * @License: GPL3
 */

jQuery(document).ready( function( $ ) {

    var myplugin_media_upload;

    $('#myplugin-change-image').click(function(e) {

        e.preventDefault();

        // If the uploader object has already been created, reopen the dialog
        if( myplugin_media_upload ) {

            myplugin_media_upload.open();
            return;

        }

        // Extend the wp.media object
        myplugin_media_upload = wp.media.frames.file_frame = wp.media({

            //button_text set by wp_localize_script()
            title: button_text.title,
            button: { text: button_text.button },
            multiple: true //allowing for multiple image selection

        });

        /**
         *THE KEY BUSINESS
         *When multiple images are selected, get the multiple attachment objects
         *and convert them into a usable array of attachments
         */
        myplugin_media_upload.on( 'select', function(){

            var attachments = myplugin_media_upload.state().get('selection').map( 

                function( attachment ) {

                    attachment.toJSON();
                    return attachment;

            });

            //loop through the array and do things with each attachment

           var i;

           for (i = 0; i < attachments.length; ++i) {

                //sample function 1: add image preview
                $('#myplugin-placeholder').after(
                    '<div class="myplugin-image-preview"><img src="' + 
                    attachments[i].attributes.url + '" ></div>'
                    );

                //sample function 2: add hidden input for each image
                $('#myplugin-placeholder').after(
                    '<input id="myplugin-image-input' +
                    attachments[i].id '" type="hidden" 
                    name="myplugin_attachment_id_array[]"  value="' + 
                    attachments[i].id + '">'
                    );

            }

        });

    myplugin_media_upload.open();

    });

});
4
  • Hey, So I am a little stumped on this and cannot seem to find a clear working answer. I tried your script there and it seems to have errors in it which is also stumping me as I cannot find where it is going wrong... Have you managed to progress this further by anychance? Commented Jun 11, 2017 at 18:13
  • Well, other than actually use it pretty much as described, I haven't felt a need to re-work it. Can you be more specific about the errors and/or the problem you're having. You can also comment at the following link, since it's not a "proper"StackEx" type dialogue, though if something significant comes up, I'd update the question/answer here: ckmacleod.com/2017/01/05/…
    – CK MacLeod
    Commented Jun 11, 2017 at 22:08
  • on myplugin_media_upload.on( 'select', function(){ , use insert instead of select.
    – mghhgm
    Commented Feb 15, 2019 at 23:33
  • @mghhgm can you explain why using insert instead of select would be an improvement?
    – CK MacLeod
    Commented Feb 17, 2019 at 18:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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