web-dev-qa-db-fra.com

Instanciez TinyMCE via JS (plutôt que PHP/wp_editor)

Une fois la page chargée, comment créer un éditeur TinyMCE?

Mettre un appel wp_editor dans une requête AJAX puis l'afficher donne ceci:

enter image description here

Les onglets visuels et textuels ne sont pas fonctionnels, pas de barre d’outils, pas d’instance TinyMCE active, juste le balisage HTML. Je dois instancier le composant JS de TinyMCE, mais comment?

J'ai également essayé de passer un appel dans ma réponse AJAX PHP à _WP_Editors::editor_js();, et je peux voir la réponse dans la console à l'aide de console.log et j'y vois le script JS, mais il n'est pas inséré dans le DOM et n'est jamais exécuté

5
Tom J Nowell

Mise à jour pour TinyMCE 4

J'ai fait des progrès

Chargez un wp_editor dans la page initiale dans une div masquée, puis effectuez l'appel AJAX pour récupérer le balisage de l'éditeur.

En PHP, vous devrez récupérer les identifiants des éditeurs créés via les appels wp_editor. Malheureusement, les variables de la classe _WP_Editors sont privées, mais nous pouvons contourner ce problème en utilisant des filtres. Pour ce faire, nous commençons par appeler le hook editor_js dans un tampon de sortie. Il tentera de générer les paramètres nécessaires et de générer le JS requis, bien que ce dernier ne fonctionne pas lorsqu'il est renvoyé via AJAX et inséré.

A la fin de cet appel, la classe _WP_Editors passe le tableau mcesettings à travers un filtre, que nous utiliserons pour créer une copie à partir de laquelle nous pouvons extraire les ID d'éditeur:

add_action( 'after_wp_tiny_mce', array( $this, 'steal_away_mcesettings' ) );

function steal_away_mcesettings( $mcesettings ) {
    $this->mcesettings = $mcesettings;
}

Donc, après avoir ajouté ce filtre, nous appelons la fonction editor_js:

ob_start();
_WP_Editors::editor_js();
ob_end_clean(); 

Nous pouvons maintenant utiliser notre copie $ mcesettings pour remplir une liste d'identifiants:

$ids = array();

foreach ( $this->mcesettings as $editor_id => $init ) {
    $ids[] = $editor_id;
}

Le tableau ids peut maintenant être renvoyé dans la réponse AJAX avec le code HTML.

Une fois dans le navigateur, nous pouvons insérer le code HTML dans la page, puis en utilisant notre editor_ids, nous pouvons instancier les instances de TinyMCE comme ceci:

function tinyMCE_bulk_init( editor_ids ) {
    var init, ed, qt, first_init, DOM, el, i;

    if ( typeof(tinymce) == 'object' ) {

        var editor;
        for ( e in tinyMCEPreInit.mceInit ) {
            editor = e;
            break;
        }
        for ( i in editor_ids ) {
            var ed_id = editor_ids[i];
            tinyMCEPreInit.mceInit[ed_id] = tinyMCEPreInit.mceInit[editor];
            tinyMCEPreInit.mceInit[ed_id]['elements'] = ed_id;
            tinyMCEPreInit.mceInit[ed_id]['body_class'] = ed_id;
            tinyMCEPreInit.mceInit[ed_id]['succesful'] =  false;
        }

        for ( ed in tinyMCEPreInit.mceInit ) {
            // check if there is an adjacent span with the class mceEditor
            if ( ! jQuery('#'+ed).next().hasClass('mceEditor') ) {
                init = tinyMCEPreInit.mceInit[ed];
                try {
                    tinymce.init(init);
                    tinymce.execCommand( 'mceAddEditor', true, ed_id );
                } catch(e){
                    console.log('failed');
                    console.log( e );
                }
            }
        }

    }
}

Étant donné que nous ne sommes pas en mesure de générer nous-mêmes les paramètres TinyMCE nécessaires pour correspondre au style WordPress, nous les volons à l'instance que nous avons créée lors du chargement initial de la page et faisons des copies. Nous modifions ensuite les copies pour utiliser les ID d'élément corrects et procédons comme d'habitude, en vérifiant que les éléments ne possèdent pas déjà d'instance.

enter image description here

Problèmes

  • Les onglets texte brut/contenu visuel ne fonctionnent pas
  • Aucune balise rapide dans la vue en texte brut
  • Le poids supplémentaire de l'instance initiale TinyMCE
  • Bouton Pas d'éditeur de média
  • Ajouter 2 instances ou plus de TinyMCE dans une demande AJAX conduit à une instance active et à la rupture des autres. Je ne suis pas sûr de savoir pourquoi, mais 2 AJAX demandes avec 1 instance chacune, vous donnent 2 instances de travail.
  • Le JS peut être modifié pour ne pas modifier la structure TinyMCEPreInit et transmettre la copie directement à l'initialiseur, en supprimant une traversée du DOM dans le processus.
3
Tom J Nowell