3.5 Media Manager – callout in metaboxes

Two ways of doing the same thing:

First one:

Read More
    var _custom_media = true,
    _orig_send_attachment = wp.media.editor.send.attachment;

    $('.media-upload-button').click(function(e) {
        var send_attachment_bkp = wp.media.editor.send.attachment;
        var button = $(this);
        var id = button.attr('id').replace('_button', '');
        console.log(id);
        _custom_media = true;
        wp.media.editor.send.attachment = function(props, attachment){
            if ( _custom_media ) {
                $('#'+id).val(attachment.url);
                $('#'+id).prev().attr('src', attachment.url);
                console.log(id);
            } else {
                return _orig_send_attachment.apply( this, [props, attachment] );
            };
        }
        wp.media.editor.open(button);
        return false;
    });

    $('.add_media').on('click', function(){
        _custom_media = false;
    });

Second one:

$('.media-upload-button').click(function(e) {
    e.preventDefault();
    var button = $(this);
    var id = button.attr('id').replace('_button', '');
    console.log(id);
    //If the uploader object has already been created, reopen the dialog
    if (custom_uploader) {
        custom_uploader.open();
        return;
    }

    //Extend the wp.media object
    custom_uploader = wp.media.frames.file_frame = wp.media({
        title: 'Wybierz zdjęcie',
        button: {
            text: 'Wybierz zdjęcie'
        },
        multiple: false
    });

    //When a file is selected, grab the URL and set it as the text field's value
    custom_uploader.on('select', function() {
        attachment = custom_uploader.state().get('selection').first().toJSON();
        $('#'+id).val(attachment.url);
        $('#'+id).prev().attr('src', attachment.url);
        //console.log(attachment);
        console.log(id);
        //custom_uploader.close();
    });

    //Open the uploader dialog
    custom_uploader.open();

});

Both works well when there is only one field/button that they are “attached” to, but if there is more than one, only first works ok. The second one always insert data to firstly clicked button/field, even if You click second one (second console.log shows oryginal “id” that is diffrent than one showed in console after click of button).

But the second interface looks better for a designed job, so the question is – how the second code should be changed, so it can work with multiple input fields/buttons?

AFAIK, the problem with second code is, that Media Manager object that is being created once, stays “in memory” so second callout only displays it, and doesnt ovverrite oryginal “custom_uploader.on” with initial id in it. Maybe somehow object should be destroyed after closing it?

To clear thing out – question is: how should I use wp.media.frames.file_frame correctly with more than one button/field instead of wp.media.editor.send.attachment?

Ps… for those, who would like to test entire code:

functions.php:

add_action( 'add_meta_boxes', 'cs_products_mb_create' );
function cs_products_mb_create() {
    //create a custom meta box
    add_meta_box( 'products-info', 'Ustawienia Produktu', 'cs_products_mb_function', 'posts', 'normal', 'high' );
}

function cs_products_mb_function( $post ) { ?>
    <div id="appcustomsettings">
        <p><input id="cs_product_menu_img_src" type="text" name="cs_product_menu_img_src" value="" /> <input id="cs_product_menu_img_src_button" type="button" value="Add / Change" class="button-secondary media-upload-button"  /></p>
        <p><input id="cs_product_bg_img_src" type="text" name="cs_product_bg_img_src" value="" /> <input id="cs_product_bg_img_src_button" type="button" value="Add / Change" class="button-secondary media-upload-button"  /></p>
    </div>
<?php   
}
add_action('admin_enqueue_scripts', 'cs_admin_customposttype_scripts');
function cs_admin_customposttype_scripts(){
    wp_enqueue_media(); 
    wp_enqueue_script( 'cs-image-upload', get_bloginfo('template_url').'/js/admin.js', array( 'jquery') );
}

Its stripped from loading and saving data, but it does what it should

The admin.js that works but uses wp.media.editor.send.attachment instead of wp.media.frames.file_frame:

jQuery(document).ready(function($){
    var _custom_media = true,
    _orig_send_attachment = wp.media.editor.send.attachment;

    $('.media-upload-button').click(function(e) {
        var send_attachment_bkp = wp.media.editor.send.attachment;
        var button = $(this);
        var id = button.attr('id').replace('_button', '');
        console.log(id);
        _custom_media = true;
        wp.media.editor.send.attachment = function(props, attachment){
            if ( _custom_media ) {
                $('#'+id).val(attachment.url);
                    console.log(id);
            } else {
                return _orig_send_attachment.apply( this, [props, attachment] );
            };
        }
        wp.media.editor.open(button);
        return false;
    });

    $('.add_media').on('click', function(){
        _custom_media = false;
    });
});

And admin.js that uses and looks as I would like, but doesnt work coccectly with two or more inputs:

jQuery(document).ready(function($){
    var custom_uploader;
    $('.media-upload-button').click(function(e) {
        e.preventDefault();
        var button = $(this);
        var id = button.attr('id').replace('_button', '');
        console.log(id);
        //If the uploader object has already been created, reopen the dialog
        if (custom_uploader) {
            custom_uploader.open();
            return;
        }

        //Extend the wp.media object
        custom_uploader = wp.media.frames.file_frame = wp.media({
            title: 'Wybierz zdjęcie',
            button: {
                text: 'Wybierz zdjęcie'
            },
            multiple: false
        });

        //When a file is selected, grab the URL and set it as the text field's value
        custom_uploader.on('select', function() {
            attachment = custom_uploader.state().get('selection').first().toJSON();
            $('#'+id).val(attachment.url);
            //console.log(attachment);
            console.log(id);
            //custom_uploader.close();
        });

        //Open the uploader dialog
        custom_uploader.open();

    });
});

Related posts

Leave a Reply

1 comment

  1. you can move the wp.media stuff to an external function which accepts the element as a parameter and call it on the click event like this:

    jQuery(document).ready(function($){
        $('.media-upload-button').click(function(e) {
            e.preventDefault();
            upload_image($(this));
            return false; 
        });
    });
    function upload_image(el){
        var $ = jQuery;
        var custom_uploader;
        var button = $(el);
        var id = button.attr('id').replace('_button', '');
        if (custom_uploader) {
            custom_uploader.open();
            return;
        }
    
        //Extend the wp.media object
        custom_uploader = wp.media.frames.file_frame = wp.media({
            title: 'Wybierz zdjęcie',
            button: {
                text: 'Wybierz zdjęcie'
            },
            multiple: false
        });
    
        //When a file is selected, grab the URL and set it as the text field's value
        custom_uploader.on('select', function() {
            attachment = custom_uploader.state().get('selection').first().toJSON();
            $('#'+id).val(attachment.url);
            $('#'+id).prev().attr('src', attachment.url);
            //console.log(attachment);
            console.log(id);
            //custom_uploader.close();
        });
    
        //Open the uploader dialog
        custom_uploader.open();
    }
    

    this way its you “overwrite” the select event each time its called, and its actualy what i use in my admin page class