8

I have created a meta-box that provides a upload function via the default media uploader from WordPress.

This works fine as long as I have one upload option.
But guess what? I want another one.

If I do this then the media box opens and I can select an image. The problem is that both input-fields are filled with the URL of the image.

I would like to be able to add multiple select options to upload images and preferably use one script.

Here is the script (output):

function dynamic_meta_callback( $post ) {
    wp_nonce_field( basename( __FILE__ ), 'dynamic_nonce' );
    $dsm = get_post_meta( $post->ID );
    $post = get_post($post_id, ARRAY_A);
    $pn = $post['post_name'];
    $a = '_'.$pn.'_1';
    $b = '_'.$pn.'_2';
?>


<div class="image_large" style="background-image: url(<?php echo $dsm['dynamic-image'.$a.''][0] ?>); background-repeat: no-repeat;">
    <p><strong>Image 1</strong></p>
    <p>
        <label for="dynamic-image" class="dynamic-row-title"><?php _e( 'Image 1', 'dynamic-textdomain' )?></label>
        <input type="text" name="dynamic-image<?php echo $a; ?>" class="dynamic-image" value="<?php if ( isset ( $dsm['dynamic-image'.$a.''] ) ) echo $dsm['dynamic-image'.$a.''][0]; ?>" />
        <input type="button" class="dynamic-image-button" class="button" value="<?php _e( 'Choose or Upload', 'dynamic-textdomain' )?>" />
    </p>
</div>
<div class="image_large" style="background-image: url(<?php echo $dsm['dynamic-image'.$b.''][0] ?>); background-repeat: no-repeat;">
    <p><strong>Image 2</strong></p>
    <p>
        <label for="dynamic-image" class="dynamic-row-title"><?php _e( 'Image2', 'dynamic-textdomain' )?></label>
        <input type="text" name="dynamic-image<?php echo $b; ?>" class="dynamic-image" value="<?php if ( isset ( $dsm['dynamic-image'.$b.''] ) ) echo $dsm['dynamic-image'.$b.''][0]; ?>" />
        <input type="button" class="dynamic-image-button" class="button" value="<?php _e( 'Choose or Upload', 'dynamic-textdomain' )?>" />
    </p>
</div>
<?php
}

Here is the save function

function dynamic_meta_save( $post_id ) {

    $post = get_post($post_id, ARRAY_A);
    $pn = $post['post_name'];
    $a = '_'.$pn.'_1';
    $b = '_'.$pn.'_2';
    // Checks save status
    $is_autosave = wp_is_post_autosave( $post_id );
    $is_revision = wp_is_post_revision( $post_id );
    $is_valid_nonce = ( isset( $_POST[ 'dynamic_nonce' ] ) && wp_verify_nonce( $_POST[ 'dynamic_nonce' ], basename( __FILE__ ) ) ) ? 'true' : 'false';

    // Exits script depending on save status
    if ( $is_autosave || $is_revision || !$is_valid_nonce ) {
        return;
    }

    // Checks for input and sanitizes/saves if needed

    // Checks for input and saves if needed
    if( isset( $_POST[ 'dynamic-image'.$a.'' ] ) ) { update_post_meta( $post_id, 'dynamic-image'.$a.'', $_POST[ 'dynamic-image'.$a.'' ] );}
    if( isset( $_POST[ 'dynamic-image'.$b.'' ] ) ) { update_post_meta( $post_id, 'dynamic-image'.$b.'', $_POST[ 'dynamic-image'.$b.'' ] );}

}
add_action( 'save_post', 'dynamic_meta_save' );

And this is the function that calls the external js and supplies data

function dynamic_image_enqueue() {  global $typenow;
$post = get_post($post_id, ARRAY_A);
if( $typenow == 'page' ) {  wp_enqueue_media();
    wp_register_script( 'dynamic-box-image', plugin_dir_url( __FILE__ ) . 'dynamic-box-image.js', array( 'jquery' ) );
    wp_localize_script( 'dynamic-box-image', 'meta_image',  
                       array('title' => __( 'Choose or Upload', 'dynamic-textdomain' ),
                             'button' => __( 'Use this image', 'dynamic-textdomain' ),
                            ));
    wp_enqueue_script( 'dynamic-box-image' );   }}
add_action( 'admin_enqueue_scripts', 'dynamic_image_enqueue' );
    }

This is what the external js looks like

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

// Instantiates the variable that holds the media library frame.
var meta_image_frame;

// Runs when the image button is clicked.

$('.dynamic-image-button').click(function(e){
    // Prevents the default action from occuring.
    e.preventDefault();
    // If the frame already exists, re-open it.
    if ( meta_image_frame ) { meta_image_frame.open(); return;}
    // Sets up the media library frame
    meta_image_frame = wp.media.frames.meta_image_frame = wp.media({title: meta_image.title,button: { text:  meta_image.button },library: { type: 'image' }});  
    // Runs when an image is selected.
    meta_image_frame.on('select', function(){ var media_attachment = meta_image_frame.state().get('selection').first().toJSON();
        $('.dynamic-image').val(media_attachment.url);  });
    // Opens the media library frame.
    meta_image_frame.open();
});
});

Hope somebody can help me out!

------------ UPDATE ------------
I have tried giving the input button a unique value and pass this on to the external .js. Found out that I have to save the value to the database everytime I have selected an image. If I don't every input field wil have the value of the last image selected!

Still struggling with this one!

2
  • Have you tried adding "multiple: true" to the "wp.media({" ?
    – Nate
    Commented Apr 20, 2017 at 11:47
  • Wait. Wut.... Wow.. I'm having a mindblow right now. Is that possible? I'll check that out. Thank you for the idea. Commented Apr 21, 2017 at 7:35

3 Answers 3

0

You can use some thing like this to add as many image as you want with the botton click for example add logos or advertisements etc

jQuery(document).ready(function($){
    var mediaUploader;
        /* function to add partner logo */
    function display_ad( button,  title, btnTxt,  inputFieldId,  outputDivId,formClass, e){
        e.preventDefault();
        if (mediaUploader) {
            mediaUploader.open();
            return;
        }
        mediaUploader = wp.media.frames.file_frame =wp.media({
            title: title,
            button:{
                text: btnTxt,
            },
            multiple:false,
        });
        mediaUploader.on('select',function(){
            attachment = mediaUploader.state().get('selection').first().toJSON();


            $( inputFieldId ).val(attachment.url);
            $( outputDivId ).css('background-image','url(' + attachment.url +')' );
            $(formClass).submit();
        });
        mediaUploader.open();
    }

    function remove_ad(inputFieldId, formClass,e){
        e.preventDefault();
        var answer = confirm("Are you sure you want to remove this logo?");
        if ( answer == true ) {
            $(inputFieldId).val('');
            $(formClass).submit();

        }
        return;
    }

    /** Different button clicks **/
    $('#logo-one').on('click',function(e){
            //display_ad( button,  title, btnTxt,  inputFieldId,  outputDivId, e)
            display_ad('#logo-one', 'Choose Logo One','Choose Logo','#sunshine-partner-one','#sunshine-partner-one-preview','.sunshine-admin-form',e);
        });
    $('#logo-two').on('click',function(e){
            display_ad('#logo-two', 'Choose Logo two','Choose Logo','#sunshine-partner-two','#sunshine-partner-two-preview','.sunshine-admin-form',e);
        });
    $('#logo-three').on('click',function(e){
            display_ad('#logo-three', 'Choose Logo Three','Choose Logo','#sunshine-partner-three','#sunshine-partner-three-preview','.sunshine-admin-form',e);
        });
    $('#logo-four').on('click',function(e){
            display_ad('#logo-four', 'Choose Logo Four','Choose Logo','#sunshine-partner-four','#sunshine-partner-four-preview','.sunshine-admin-form',e);
        });
    $('#logo-five').on('click',function(e){
            display_ad('#logo-five', 'Choose Logo Five','Choose Logo','#sunshine-partner-five','#sunshine-partner-five-preview','.sunshine-admin-form',e);
        });
    $('#logo-six').on('click',function(e){
            display_ad('#logo-six', 'Choose Logo Six','Choose Logo','#sunshine-partner-six','#sunshine-partner-six-preview','.sunshine-admin-form',e);
        });
    /*Romove button click*/
    $('#remove-logo-one').on('click',function(e){
        remove_ad('#sunshine-partner-one','.sunshine-admin-form',e);
    });
    $('#remove-logo-two').on('click',function(e){
        remove_ad('#sunshine-partner-two','.sunshine-admin-form',e);
    });
    $('#remove-logo-three').on('click',function(e){
        remove_ad('#sunshine-partner-three','.sunshine-admin-form',e);
    });
    $('#remove-logo-four').on('click',function(e){
        remove_ad('#sunshine-partner-four','.sunshine-admin-form',e);
    });
    $('#remove-logo-five').on('click',function(e){
        remove_ad('#sunshine-partner-five','.sunshine-admin-form',e);
    });
    $('#remove-logo-six').on('click',function(e){
        remove_ad('#sunshine-partner-six','.sunshine-admin-form',e);
    });

}); 
0

I'm not sure this is conclusive, but it's likely playing a role. You have 2 inputs, both with class dynamic-image:

<input type="text" name="dynamic-image<?php echo $a; ?>" class="dynamic-image" value="<?php if ( isset ( $dsm['dynamic-image'.$a.''] ) ) echo $dsm['dynamic-image'.$a.''][0]; ?>" />

and

<input type="text" name="dynamic-image<?php echo $b; ?>" class="dynamic-image" value="<?php if ( isset ( $dsm['dynamic-image'.$b.''] ) ) echo $dsm['dynamic-image'.$b.''][0]; ?>" />

In your JS script, you're then doing this:

meta_image_frame.on('select', function() { 
    var media_attachment = ...
    $('.dynamic-image').val(media_attachment.url);  
    ...
});

When you select a file in your media frame, the line $('.dynamic-image').val(media_attachment.url); will fill both inputs with the same attachment URL.

You could add a data- attribute to your upload buttons instead, like this:

<input type="button" ... data-target="dynamic-image<?php echo $a; ?>" />

then read it in your JS script, like this:

meta_image_frame.on('select', function(){ 
    var media_attachment = ... meta_image_frame.state().get('selection').first().toJSON();
        $('[name="' + $( e.target ).attr( 'data-target' ) + '"]').val(media_attachment.url);  });

That should only update the relevant input, depending on which upload button you click.

0

Try to target the Id's of input fields rather than classes. That will work out fine. And in Save_Function, make sure that each image is saved seperatly and have its URL available.

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.