wp.media.view.ImageDetails: guarda la configuración como datos HTML5 * atributos para la imagen

19

Lo que finalmente quiero lograr son configuraciones adicionales agregadas al cuadro Detalles de imagen, que se almacenarán en la <img>etiqueta de imagen como data-*atributos

Ejemplo: <img src="..." data-my_setting="...">


MI CÓDIGO

Estoy creando un complemento y necesito crear más configuraciones para cuando editas imágenes. Hasta ahora tengo el siguiente código:

jQuery(function($) {

    var imageDetails = wp.media.view.ImageDetails

    wp.media.view.ImageDetails = wp.media.view.ImageDetails.extend({
        // Initialize - Call function to add settings when rendered
        initialize: function() {
            this.on('post-render', this.add_settings);
        },
        // To add the Settings
        add_settings: function() {
            $('.advanced-section').prepend('\
                <h2>My Settings</h2>\
                <input type="text" class="my_setting">\
            ');

            // Set Options
            this.controller.image.set({"data-settings": 'setting-value-here'})
        }
    });

}) // End of jQuery(function($))

Creé una nueva publicación y agregué una imagen, luego hice clic en ella y presioné Editar (el ícono de lápiz en la barra de herramientas que apareció). Terminé en la página de detalles de la imagen, y así es como se veía:

ingrese la descripción de la imagen aquí

Hasta aquí todo bien. En esta línea:

this.controller.image.set({"data-settings": 'setting-value-here'})

Normalmente usaría jQuery para obtener el valor de la entrada, pero para fines de prueba lo cambié para que sea un valor estático de 'setting-value-here'. Presioné 'Actualizar' en la esquina inferior derecha del cuadro Detalles de imagen.


EL PROBLEMA

En el editor de texto, muestra el código HTML como este:

ingrese la descripción de la imagen aquí

Esto no tiene un data-settings="setting-value-here", ¿cómo es que?

Si reemplazo la línea con esto:

 this.controller.image.set({alt: 'setting-value-here'})

Se hace cambiar la ALT etiqueta a alt="setting-value-here". Entonces, ¿qué estoy haciendo mal tratando de establecer el atributo data- *?


LA SOLUCIÓN

Gracias a @bonger (que obtuvo la recompensa completa de 50 Reputación), tengo el siguiente código:

PHP:

function add_my_settings() {
    ob_start();
    wp_print_media_templates();
    $tpl = ob_get_clean();
    if ( ( $idx = strpos( $tpl, 'tmpl-image-details' ) ) !== false
            && ( $before_idx = strpos( $tpl, '<div class="advanced-section">', $idx ) ) !== false ) {
        ob_start();
        ?>
        <div class="my_setting-section">
            <h2><?php _e( 'My Settings' ); ?></h2>
            <div class="my_setting">
                <label class="setting my_setting">
                    <span><?php _e( 'My Setting' ); ?></span>
                        <input type="text" data-setting="my_setting" value="{{ data.model.my_setting }}" />
                    </label>
                </div>
            </div>
        <?php
        $my_section = ob_get_clean();
        $tpl = substr_replace( $tpl, $my_section, $before_idx, 0 );
    }
    echo $tpl;
};

// Hack the output of wp_print_media_templates()
add_action('wp_enqueue_media', $func =
    function() {
        remove_action('admin_footer', 'wp_print_media_templates');
        add_action('admin_footer',  'add_my_settings');
    }
);

JavaScript: (debe ponerse en cola usando wp_enqueue_script())

// When Image is Edited
wp.media.events.on('editor:image-edit', function(data) {
    data.metadata.my_setting = data.editor.dom.getAttrib( data.image, 'data-my_setting' );
});

// When Image is Updated
wp.media.events.on('editor:image-update', function(data) {
    data.editor.dom.setAttrib( data.image, 'data-my_setting', data.metadata.my_setting );
});
Kaspar Lee
fuente
3
Desearía poder +2: elocuente, conciso, bien investigado, por lo que me duele mucho el tema. Preguntas como estas son raras.
TheDeadMedic
2
¡Gracias! Siempre trato de investigar (y depurar) mis problemas tanto como puedo antes de preguntar. (Odio cuando encuentras una pregunta realmente simple y el OP ni siquiera ha intentado buscar en Google)
Kaspar Lee

Respuestas:

14

Una forma de hacerlo es usar los (muy convenientes) editor:image-edity editor:image-updateeventos activados por el wpeditimagecomplemento tinymce para obtener / configurar el dom directamente ( actualizado para envolver en wp_enqueue_mediaacción):

add_action( 'wp_enqueue_media', function () {
    add_action( 'admin_footer', function () {
        ?>
        <script type="text/javascript">
        jQuery(function ($) {
            if (wp && wp.media && wp.media.events) {
                wp.media.events.on( 'editor:image-edit', function (data) {
                    data.metadata.my_setting = data.editor.dom.getAttrib( data.image, 'data-my_setting' );
                } );
                wp.media.events.on( 'editor:image-update', function (data) {
                    data.editor.dom.setAttrib( data.image, 'data-my_setting', data.metadata.my_setting );
                } );
            }
        });
        </script>
        <?php
    }, 11 );
} );

Para agregar y completar el campo de configuración, quizás sea mejor piratear la salida en wp_print_media_templates()lugar de anular ImageDetails.initialize()( actualizado para ajustar en wp_enqueue_mediaacción):

add_action( 'wp_enqueue_media', function () {
    remove_action( 'admin_footer', 'wp_print_media_templates' );
    add_action( 'admin_footer', $func = function () {
        ob_start();
        wp_print_media_templates();
        $tpl = ob_get_clean();
        // To future-proof a bit, search first for the template and then for the section.
        if ( ( $idx = strpos( $tpl, 'tmpl-image-details' ) ) !== false
                && ( $before_idx = strpos( $tpl, '<div class="advanced-section">', $idx ) ) !== false ) {
            ob_start();
            ?>
    <div class="my_setting-section">
        <h2><?php _e( 'My Settings' ); ?></h2>
        <div class="my_setting">
            <label class="setting my_setting">
                <span><?php _e( 'My Setting' ); ?></span>
                <input type="text" data-setting="my_setting" value="{{ data.model.my_setting }}" />
            </label>
        </div>
    </div>
            <?php
            $my_section = ob_get_clean();
            $tpl = substr_replace( $tpl, $my_section, $before_idx, 0 );
        }
        echo $tpl;
    } );
} );
bonger
fuente
2
Muchas gracias! Esto es muy útil (aunque lleva unos minutos entenderlo). Aceptaré la respuesta y te otorgaré la recompensa justo antes de que termine (a alguien se me ocurre una respuesta mejor / más simple)
Kaspar Lee
Hmm, eso sucederá si se ejecuta antes wp_enqueue_media(). Quizás una manera más agradable es el uso de la wp_enqueue_mediaacción que se desencadena al final wp_enqueue_media(), es decir, envolver todo el código en unadd_action( 'wp_enqueue_media', function () { /*the code*/ } );
Bonger
¡No, viceversa!
bonger
Actualizaré la respuesta ...
bonger
1
Es la anulación de WP de las cosas de la plantilla de subrayado underscorejs.org/#template (ver wp.templateen "wp-includes / js / wp-util.js") .... Creo
bonger