web-dev-qa-db-fra.com

Pourquoi wp_editor ne peut-il pas être utilisé dans un widget personnalisé?

Je travaille sur le développement d'un plugin qui ajoute un widget qui vous permet d'éditer le contenu avec un éditeur wysiwyg. Je veux utiliser l'éditeur WordPress par défaut en appelant wp_editor(). J'ai vu des gens dire que vous ne pouvez pas faire cela, et bien sûr, cela se bloque lorsque vous essayez de mettre à jour le contenu du widget.

Quelqu'un peut-il expliquer pourquoi wp_editor() ne peut pas être utilisé dans des widgets?

J'espère comprendre comment contourner ce problème une fois que je saurai pourquoi cela ne fonctionne pas. Cependant, Chrome ne génère aucune erreur dans la console. Par conséquent, je ne suis pas sûr de savoir si cela risque de provoquer des bugs.

Merci, goldentoa11

3
Goldentoa11

Réponse courte: car il y a un widget caché où TinyMCE apparaît en premier.

Réponse longue (désolé, une réponse très longue):

Allez dans le Codex et copiez le widget exemple Foo_Widget pour vous assurer que nous parlons du même code. Ouvrez maintenant votre IDE (pas un éditeur) et écrivez un petit widget de test sous forme de plugin. Commençant par un en-tête de plugin minimal ...

<?php
/*
Plugin Name: Widget Test Plugin
Description: Testing plugincode
*/

... en ajoutant le code du widget à partir du codex et en enregistrant le widget avec l'appel add_action(). Modifiez maintenant la méthode form dans la classe de widget, comme indiqué ci-dessous:

public function form( $instance ) {
    if ( isset( $instance[ 'title' ] ) ) {
        $title = $instance[ 'title' ];
    }
    else {
        $title = __( 'New title', 'text_domain' );
    }
    ?>
    <p>
    <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
    <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
    </p>
    <?php

/*** add this code ***/
    $content   = 'Hello World!';
    $editor_id = 'widget_editor';

    $settings = array(
        'media_buttons' => false,
        'textarea_rows' => 3,
        'teeny'         => true,
    );

    wp_editor( $content, $editor_id, $settings );
/*** end editing ***/
}

Allez sur votre blog, activez le plugin, allez à la page du widget et faites glisser le Foo Widget dans une barre latérale. Vous verrez que cela va échouer.

Voyez-vous la description Foo Widget sur le côté gauche? Faites un clic droit sur la description et choisissez "Inspecter" dans vos outils de développement (vous avez des outils de développement tels que FireBug ou Chrome DevTools, hein? Dans FireFox, vous pouvez également choisir la construction dans "Inspecter un élément"). Parcourez le code HTML et vous verrez qu'il y a un éditeur dans le widget 'caché'. wp_editor in the hidden widget

Vous pouvez voir un éditeur dans la barre latérale à droite et un éditeur dans le widget "masqué" à gauche. Cela ne peut pas fonctionner correctement car TinyMCE ne sait pas quel éditeur doit être utilisé.

De quoi avons-nous besoin?

Nous avons besoin d'un unique ID pour notre éditeur.

/*** add this code ***/
    $Rand    = Rand( 0, 999 );
    $ed_id   = $this->get_field_id( 'wp_editor_' . $Rand );
    $ed_name = $this->get_field_name( 'wp_editor_' . $Rand );

    $content   = 'Hello World!';
    $editor_id = $ed_id;

      $settings = array(
      'media_buttons' => false,
      'textarea_rows' => 3,
      'textarea_name' => $ed_name,
      'teeny'         => true,
    );

    wp_editor( $content, $editor_id, $settings );
/*** end edit ***/

Modifiez le code dans la méthode form à nouveau avec le code ci-dessus. Nous créons un numéro unique avec Rand() et ajoutons ce numéro aux attributs id et name. Mais arrêtez, qu'en est-il de sauver les valeurs ???

Accédez à la méthode update et ajoutez die(var_dump($new_instance)); à la première ligne. Si vous appuyez sur Save sur le widget, le script mourra et affichera les valeurs soumises. Vous verrez qu'il existe une valeur telle que wp_editor_528. Si vous rechargez la page et enregistrez le widget à nouveau, le numéro sera remplacé par un autre nom, car il s'agit d'un nombre aléatoire.

Comment saurai-je quel nombre aléatoire a été défini dans le widget? Envoyez simplement le nombre aléatoire avec les données du widget. Ajoutez ceci à la méthode form

printf(
  '<input type="hidden" id="%s" name="%s" value="%d" />',
  $this->get_field_id( 'the_random_number' ),
  $this->get_field_name( 'the_random_number' ),
  $Rand
);

Dans la routine de mise à jour, nous pouvons maintenant accéder au nombre aléatoire avec $new_instance['the_random_number']; et accéder ainsi au contenu de l'éditeur avec

$Rand = (int) $new_instance['the_random_number'];
$editor_content = $new_instance[ 'wp_editor_' . $Rand ];
die(var_dump($editor_content));

Comme vous pouvez le constater, le contenu de l'éditeur sera soumis et vous pouvez l'enregistrer ou faire autre chose.

Avertissement

Le contenu de l'éditeur n'est correctement soumis que si TinyMCE est not en mode visuel (mode WYSIWYG). Vous devez passer en mode texte avant d'appuyer sur "Enregistrer". Sinon, le contenu prédéfini (dans ce cas, $content = 'Hello World!';) est soumis. Je ne sais pas pourquoi maintenant, mais il existe une solution de contournement simple pour cela.

Écrivez un petit script jQuery qui déclenche le clic sur l'onglet "texte" avant d'enregistrer le contenu du widget.

JavaScript (enregistré en tant que widget_script.js quelque part dans vos dossiers theme/plugin):

jQuery(document).ready(
    function($) {
        $( '.widget-control-save' ).click(
            function() {
                // grab the ID of the save button
                var saveID   = $( this ).attr( 'id' );

                // grab the 'global' ID
                var ID       = saveID.replace( /-savewidget/, '' );

                // create the ID for the random-number-input with global ID and input-ID
                var numberID = ID + '-the_random_number';

                // grab the value from input field
                var randNum  = $( '#'+numberID ).val();

                // create the ID for the text tab
                var textTab  = ID + '-wp_editor_' + randNum + '-html';

                // trigger a click
                $( '#'+textTab ).trigger( 'click' );

            }
        );
    }
);

Et le mettre en file d'attente

function widget_script(){

    global $pagenow;

    if ( 'widgets.php' === $pagenow )
        wp_enqueue_script( 'widget-script', plugins_url( 'widget_script.js', __FILE__ ), array( 'jquery' ), false, true );

}

add_action( 'admin_init', 'widget_script' );

C'est tout. Facile, n'est ce pas? ;)

10
Ralf912

Il est tout à fait possible de réaliser tinyMCE dans un widget. En fait cela a déjà été fait . Le simple fait d'appeler wp_editor() dans un formulaire de widget s'explique par le fait que le balisage de formulaire est remis de manière asynchrone à l'aide d'AJAX. Essayez chercher ici pour plus de détails.

1
Zlatev

je ne connais pas la réponse exacte à la raison pour laquelle wp_editor () ne fonctionne pas dans les widgets, mais les widgets ont certaines restrictions.

Mais wp_editor n’est que l’une des nombreuses possibilités d’utiliser l’éditeur visuel dans le backend de WordPress. Essayez d’initialiser l’éditeur visuel avec jQuery d’une manière ou d’une autre. Je ne pense pas que vous puissiez le faire à l'intérieur de la fenêtre du widget, mais une lightbox ou quelque chose comme ça pourrait aider.

Voici un moyen de le faire:

/**
 * Add TinyMCE to multiple Textareas (usually in backend).
 */
//  add_action('admin_print_footer_scripts','my_admin_print_footer_scripts',99);
function my_admin_print_footer_scripts() {
    ?><script type="text/javascript">/* <![CDATA[ */
        jQuery(function($)
        {
            var i=1;
            $('.customEditor textarea').each(function(e)
            {
                var id = $(this).attr('id');

                if (!id)
                {
                    id = 'customEditor-' + i++;
                    $(this).attr('id',id);
                }

                tinyMCE.execCommand('mceAddControl', false, id);

            });
        });
    /* ]]> */</script><?php
}
1
Blackbam