É possível reutilizar o wp.media.editor Modal para diálogos diferentes da mídia

30

Para expandir: eu gostaria de utilizar o mesmo código / aparência modal (usado em wp.media.Modal, wp.media.FocusManager) para abrir um modal da minha própria caixa de diálogo personalizada, não do Editor de Mídia. No passado, eu usei o thickbox para esse tipo de coisa, mas o wp.media.Modal parece ser o caminho do futuro para os modais - sem mencionar que parece legal.

Eu cutuquei um pouco a fonte JS e cheguei a algumas soluções possíveis:

  1. "Empreste" o código media-views.js e use-o no meu plugin.
  2. "Estenda" wp.media.Modal (afinal, é uma exibição de backbone).
  3. Crie uma implementação customizada, jQueryUI, etc.
  4. Apenas desista e use o thickbox.

O empréstimo parece um pouco menos perigoso do que usar wp.media.Model.extend ({}), mas é um desperdício. Eu não sou um grande fã dos modais do jQueryUI, mas faria o trabalho. Ao mesmo tempo, eu poderia fazer uma implementação personalizada de modais (ou baseá-la em outra biblioteca).

Parece que estou perdendo algo óbvio: mais alguém conseguiu isso ou o novo código modal da biblioteca de mídia é "novo demais" para permitir a reutilização?

Jer
fonte
3
Parece que você está perdendo a experiência. Eu recomendo ir para o # 2: provavelmente o mais limpo e o mais desafiador / divertido, além de parecer que você conhece o Backbone.
precisa
2
por favor, compartilhe suas descobertas!
paul
Tutorial / plugin interessante em github.com/ericandrewlewis/wp-media-javascript-guide - documentação interativa para o Javascript que alimenta o WP Media .
jgraup

Respostas:

12

Resposta tardia e edição. Isenção de responsabilidade: O código a seguir não é de copiar e colar.

Esboço áspero

Como eu nunca tentei usar mal o modal de mídia para mais nada, aqui está uma breve visão geral, esboçada ao interromper uma parte de um projeto em que estou atualmente. É não um pronto para ir exemplo, mas deve trazê-lo perto o suficiente. Basta ler os comentários com atenção e implementar o seguinte PHP em seus objetos.

PHP

Em nosso construtor, registramos nossos scripts, adicionamos meta boxes que contêm informações e um botão de mídia, filtramos tipos MIME adicionais (por exemplo, ZIP) e nos preocupamos em salvar os dados adicionais:

public function __construct()
{
    add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );

    foreach( $this->post_types as $post_type )
        add_action( "add_meta_boxes_{$post_type}", array( $this, 'add_meta_box' ) );

    add_filter( 'media_view_settings', array( $this, 'filter_media_view_settings' ), 10, 2 );

    add_action( 'wp_insert_post_data', array( $this, 'wp_insert_post_data' ), 10, 2 );
}

Anule se não precisar desse script em uma página específica. Isso economiza memória, solicita tempo e ajuda a manter sua instalação limpa.

public function enqueue_scripts( $page )
{
    if (
        ! in_array( $page, array( 'post.php', 'post-new.php' ) )
        # Assuming that there's a class property array that holds post types we want to add to
        # OR ! in_array( get_current_screen()->post_type, array_keys( $this->post_types ) )
    )
        return;

    wp_enqueue_media();
    wp_enqueue_script(
        'wpse_media_modal',
        plugins_url( 'assets/js/media-modal.js', dirname( __FILE__ ) ),
        array(
            # 'jquery',
            'media-views'
        ),
        null,
        true
    );
    wp_localize_script(
        'wpse_media_modal',
        'wpse_obj',
        $this->get_media_props()
    );
}

Em seguida, adicionamos a caixa meta. Dentro da função, podemos confiar na propriedade de $postobjetos post_type, que também será definida para novas postagens. Como já registramos os retornos de chamada no construtor nos ganchos contextuais apropriados, podemos simplesmente aceitar qualquer tipo de post que aparecer.

public function add_meta_box( $post )
{
    add_meta_box(
        'wprd_upload',
        __( 'Upload', 'our_textdomain' ),
        array( $this, 'render_content' ),
        $post->post_type,
        'advanced',
        'default',
        array()
    );
}

Tipos MIME adicionais

Simplesmente jogue uma matriz que substitua ou adicione aos tipos MIME padrão do Media Modal. Você também pode adicionar ou substituir outras configurações. Apenas var_dump( $settings );para ver o que o retorno de chamada fornece. Verifique também se não interceptamos o tipo de postagem errado.

public function filter_media_view_settings( $settings, $post )
{
    if ( ! in_array( $post->post_type, array_keys( $this->post_types ) ) )
        return $settings;

    $settings['mimeTypes'] += array( 'application/zip' );

    return $settings;
}

Renderizar o conteúdo

public function render_content()
{
    $props = array(
        'modalTitle'      => __( 'Select ZIP Archives', 'our_textdomain' ),

        // The following data is what we will access later
        // SomeIDfromLocalizedScriptOBJ
        'buttonID'        => 'open-media-lib',
        'buttonClass'     => 'open-media-button',
        'buttonText'      => __( 'Add ZIP', 'our_textdomain' ),
        'buttonDataText'  => __( 'Select', 'our_textdomain' ),
        'buttonDataTitle' => __( 'Select Whatever', 'our_textdomain' ),

        'mimeTypes'       => array(
            $zip => __( 'ZIP Archive', 'our_textdomain' ),
        ),
    );

    wp_nonce_field( plugin_basename( __FILE__ ), $this->nonce_name );
    ?>
    <input type="button"
           class="button <?php echo $props['buttonClass']; ?>"
           id="<?php echo $props['buttonID']; ?>"
           value="<?php echo $props['buttonText']; ?>"
           data-title="<?php echo $props['buttonDataTitle']; ?>"
           data-button-text="<?php echo $props['buttonDataText']; ?>" />
}

Salve os dados

Finalmente, garantimos que nossos dados sejam salvos corretamente e serão verificados. Use todas as esc_*()funções, tipecasting, nonces e quais não.

public function wp_insert_post_data( $data, $post_array )
{
    if (
        ! in_array( $post_array['post_type'], array_keys( $this->post_types ) )
        # OR ( defined( 'DOING_AUTOSAVE' ) AND DOING_AUTOSAVE )
        OR ! isset( $_POST[ $this->nonce_name ] )
        OR ! wp_verify_nonce( $_POST[ $this->nonce_name ], plugin_basename( __FILE__ ) )
    )
        return $data;

    $post_array['zip'] = array_map( 'array_filter', $post_array['zip'] );

    $id = $post_array['ID'];
    update_post_meta(
        $id,
        'zip',
        $post_array['zip'],
        get_post_meta( $id, 'zip' )
    );

    return $data;
}

Nota final, antes de seguir para o exemplo do JS: O código está quebrado em um projeto atual. Portanto, como já mencionado, ele não funcionará por padrão! É apenas um guia e nada mais.

Javascript

O javascript em si é bastante simples. Não. Mas como você pode ver, estou injetando o jQuery e o objeto de script localizado personalizado na função. A partir daí, você terá que adicionar qualquer lógica que possa precisar. O ambiente básico para diferentes estados e retornos de chamada é fornecido console.log()es estão presentes.

var ds = ds || {};

( function( $, obj ) {
    var media;

    ds.media = media = {};

    _.extend( media, {
        view: {},
        controller: {}
    } );

    media.buttonID    = '#' + obj.buttonID,

    _.extend( media, {
        frame: function() {
            if ( this._frame )
                return this._frame;

            var states = [
                new wp.media.controller.Library(),
                new wp.media.controller.Library( {
                    id:                 'image',
                    title:              'Images',
                    priority:           20,
                    searchable:         false,
                    library:            wp.media.query( { type: 'image' } ),
                    multiple:           true
                } ),
                /*new wp.media.controller.Library( {
                    id:                 'video',
                    title:              'Video',
                    priority:           40,
                    library:            wp.media.query( { type: 'video' } ),
                    multiple:           false,
                    contentUserSetting: false // Show the Upload Files tab.
                } ),*/
                new wp.media.controller.Library( {
                    id:                 obj.SomeIDfromLocalizedScriptOBJ,
                    title:              obj.SomeTitlefromLocalizedScriptOBJ,
                    priority:           30,
                    searchable:         true,
                    // filterable:         'uploaded',
                    library:            wp.media.query( { type: obj.SomeMIMETypesfromLocalizedScriptOBJ } ),
                    multiple:           true
                    // contentUserSetting: true
                } ),
            ];

            this._frame = wp.media( {
                // className: 'media-frame no-sidebar',
                states: states
                // frame: 'post'
            } );

            this._frame.on( 'open', this.open );

            this._frame.on( 'ready', this.ready );

            this._frame.on( 'close', this.close );

            this._frame.on( 'menu:render:default', this.menuRender );

            this._frame.state( 'library' ).on( 'select', this.select );
            this._frame.state( 'image' ).on( 'select', this.select );
            this._frame.state( obj.ZIPTabID ).on( 'select', this.select );

            return this._frame;
        },

        open: function() {
            console.log( 'Frame opened' );
        },

        ready: function() {
            console.log( 'Frame ready' );
        },

        close: function() {
            console.log( 'Frame closed' );
        },

        menuRender: function( view ) {
            /* view.unset( 'library-separator' );
            view.unset( 'embed' );
            view.unset( 'gallery' ); */
        },

        select: function() {
            var settings = wp.media.view.settings,
                selection = this.get( 'selection' );

            selection.map( media.showAttachmentDetails );
        },

        showAttachmentDetails: function( attachment ) {
            // This function normally is used to display attachments
            // Handle removal of rows
            media.removeAttachmentRow( /* some var */ );
        },

        removeAttachmentRow: function( row ) {
            // Remove stuff callback
        },

        init: function() {
            // Open media frame
            $( media.buttonID ).on( 'click.media_frame_open', function( e ) {
                e.preventDefault();

                media.frame().open();
            } );
        }
    } );

    $( media.init );
} )( jQuery, wpse_obj );

Tutoriais

Dominik Schilling - o autor do gerenciador de mídia WP 3.5 - escreveu um conjunto de demos para os modais de mídia. Você pode vê-los no GitHub .

kaiser
fonte