Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Two ways of doing the same thing:

First one:

    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();

    });
});
share|improve this question
2  
I'm unaware of any previous questions you've asked. For the purposes of context could you state clearly in 1 sentence as concisely as possible what your question is? I get the feeling your second to last paragraph almost does that but it's buried amongst a lot of description. Treat it as a "How do I do X, I tried Y, here are the details of what I have" –  Tom J Nowell Feb 14 '13 at 9:54
    
I've edited the question :). –  Marcin Bobowski Feb 14 '13 at 11:36
    
Edited question again and provided two versions of working code (ready to paste to functions.php and admin.js) for testing. –  Marcin Bobowski Feb 14 '13 at 12:12
add comment

1 Answer

up vote 4 down vote accepted

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

share|improve this answer
    
And this saved my day - great solution, I've only corrected some little errors in Your code (function name an element name) and it wokrs like a charm. Thanks a lot :). –  Marcin Bobowski Feb 14 '13 at 13:40
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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