Cómo cargar wp_editor() a través de AJAX/jQuery
Tengo un tema desarrollado a medida que es realmente complejo. Una de las funcionalidades que tiene son múltiples áreas de contenido donde los usuarios pueden especificar contenido para pestañas específicas. Cargo múltiples instancias del editor de WordPress a través de la función wp_editor()
. Funciona perfectamente. (Todo esto en el lado de administración, en el tipo de post "Page")
Sin embargo, comencé a hacer algunas mejoras, incluyendo la capacidad de agregar/eliminar pestañas dinámicamente (antes, cargaba 6 editores en la página). Los usuarios pueden tener de 1 a 7 pestañas.
Cuando los usuarios agregan una pestaña, necesita añadir una instancia del editor a la página. Sin embargo, sin importar lo que intente, no puedo hacer que se cargue y se muestre correctamente.
Aquí están las 2 cosas que he intentado hasta ahora:
- Crear un archivo php que tiene incluido el bootstrap de administración, y luego cargar el editor con
wp_editor()
. Después hago un$.load
con jQuery para llamar a la página e incluir el HTML resultante en el área donde necesita mostrarse. Sin embargo, esto no funciona realmente, ya que los botones de formato del editor desaparecen (vale la pena mencionar que al cargar la página directamente, el editor se muestra y funciona perfectamente) - Cargar el editor en la página, dentro de un div oculto, y luego una vez que se agrega una pestaña, usar jQuery para moverlo a su lugar. Esto carga el editor intacto, pero no se pueden usar ninguno de los botones del editor (se muestran, pero no hacen nada), y no puedes poner el cursor en el área de texto (curiosamente, cambiar al modo HTML permite escribir y alguna interacción con los botones del modo HTML)
Entonces la pregunta es, ¿alguien ha tenido éxito agregando editores a través de llamadas AJAX? ¿Algún consejo?
Para que aparezcan los quicktags, necesitas reinstanciarlos dentro de tu manejador oncomplete de ajax.
quicktags({id : 'editorcontentid'});
Mi manejador de éxito de ajax se ve así:
success: function(data, textStatus, XMLHttpRequest){
//añadir editor al DOM
$('#container').append($(data).html());
//inicializar quicktags
quicktags({id : 'editorcontentid'});
//inicializar tinymce
tinymce.init(tinyMCEPreInit.mceInit['editorcontentid']);
}
He logrado cargar el editor llamando primero a una función estática que crea el editor y lo guarda en caché como variable. Ejecuto el método de creación del editor al inicializar. Esto parece hacer que WordPress encole todos los scripts necesarios.
Es importante que cuando crees tu instancia de editor, la configures para usar tinymce, de esa manera el archivo js de tinymce también se encola.

tinymce es un recurso externo, así que creo que podrían pensar que la propia documentación de tinymce lo cubre - https://www.tinymce.com/docs/ - pero bastante pobre en ejemplos... ¡También debes incluir los scripts de tinymce para que esta respuesta funcione! (la forma más simple es generar un editor PHP ficticio con wp_editor()
usando el argumento tinymce
establecido en true
:-)

Solución final funcional:
Añadir una acción en WordPress, por ejemplo My_Action_Name
(también nota el ID del textarea My_TextAreaID_22
):
add_action('wp_ajax_My_Action_Name', function(){
wp_editor( $_POST['default_text'], 'My_TextAreaID_22', $settings = array( 'tinymce'=>true, 'textarea_name'=>'name77', 'wpautop' =>false, 'media_buttons' => true , 'teeny' => false, 'quicktags'=>true, ) ); exit;
});
Ahora, en el panel de administración, ejecutar esta función (nota el uso de My_TextAreaID_22
y My_Action_Name
):
function start_Ajax_request() {
My_New_Global_Settings = tinyMCEPreInit.mceInit.content; // Obtener CONFIGURACIONES por defecto de WordPress (no puedo confirmar, pero si necesitas cambiar el ID objetivo, añade esta línea: My_New_Global_Settings.selector = "My_TextAreaID_22"; )
jQuery.post(ajaxurl,
{ action: "My_Action_Name", default_text: "Hola Mundo"},
function(response,status){
tinymce.init(My_New_Global_Settings);
tinyMCE.execCommand('mceAddEditor', false, "My_TextAreaID_22");
quicktags({id : "My_TextAreaID_22"});
// tinyMCE.execCommand( 'mceAddEditor', true, element.id );
}
);
}
start_Ajax_request(); // < ---- EJECUTAR

Necesitas llamar nuevamente la inicialización del editor después de añadir tu área de texto AJAX, lo hice así:
$.fn.tinymce_textareas = function(){
tinyMCE.init({
skin : "wp_theme"
// otras opciones aquí
});
};
Luego llama a tu función después de tu AJAX, así:
$('#my_new_textarea_container').html(response).tinymce_textareas();

Por favor, explica ¿cómo funciona esto? Esto no funciona. Lo he intentado.

La solución utilizable de @toscho en github. Él construyó este buen resultado también para una pregunta aquí, consulta su respuesta para más detalles.

Lo solucioné de la siguiente manera:
- Primero necesitas llamar a wp_editor en la página principal, desde donde llamas al ajax. Pero debes envolverlo en un div oculto:
<div style="display:none">
<?php
wp_editor( '', 'unique_id', array(
'media_buttons' => false,
'textarea_rows' => 10,
'teeny' => true,
) );
?>
</div>
El ID debe ser aleatorio y único. Los ajustes deben ser los mismos que los ajustes en tu editor ajax.
- Segundo, necesitas llamar esto en la respuesta ajax:
wp_editor( '', '[establece el id como necesites]', array(los mismos ajustes que en la página principal) );
_WP_Editors::editor_js(); //esto imprime el código de inicialización del editor

Esto funcionará en las páginas de administración.
Para agregar un nuevo editor wp a un contenedor mediante JS AJAX:
1) Crear una función wp_ajax en functions.php para devolver el wp_editor
2) Crear un script jQuery para solicitar un nuevo editor de texto y agregarlo a un contenedor, para este caso, al presionar un botón
Archivo PHP
function yourprefix_get_text_editor() {
$content = ""; // Vacío porque es un nuevo editor
$editor_id = $_POST["text_editor_id"]; // ID aleatorio desde la llamada AJAX JS
$textarea_name = $_POST["textarea_name"]; // Nombre desde el archivo JS
$settings = array(
'textarea_name' => $textarea_name
);
wp_editor($content, $editor_id, $settings);
wp_die(); // Obligatorio wp_die
}
add_action('wp_ajax_yourprefix_get_text_editor', 'yourprefix_get_text_editor');
Script JS (jsfile.js)
jQuery(function($) {
$("someelement").click(function(e) { // Para agregar un editor al hacer clic en un botón
var target = themeajax.ajax_url; // Pasado desde wp_localize_script
var editor_id = "editorid"; // Generar esto dinámicamente
var textarea_name = "textareaname" // Generar esto según lo necesites
var data = {
'action': 'yourprefix_get_text_editor',
'text_editor_id': editor_id,
'textarea_name': textarea_name
}
$.post(target, data, function(response) {
container.append(response); // Usa tu lógica para obtener el contenedor donde quieres agregar el editor
tinymce.execCommand('mceAddEditor', false, editor_id);
quicktags({id : editor_id});
});
}
});
Llamada para encolar scripts:
function yourprefix_admin_scripts($hook) {
wp_enqueue_script('your-slug', get_stylesheet_directory_uri() . '/path/to/jsfile.js', array('jquery'), null, true);
wp_localize_script('your-slug', 'themeajax', array(
'ajax_url' => admin_url('admin-ajax.php')
));
}
add_action('admin_enqueue_scripts', 'yourprefix_admin_scripts');

Usa este código, espero que te ayude:
wp_editor( '', 'custom_editor_id' );
\_WP_Editors::enqueue_scripts();
print_footer_scripts();
\_WP_Editors::editor_js();
Más detalles se pueden encontrar aquí.

Por favor comparte un resumen de cómo este código puede ayudar, y luego añade el enlace para más detalles. Las respuestas que solo contienen enlaces se vuelven inválidas si el enlace se rompe - espero que lo entiendas. :)

Ese enlace está roto ahora mismo y no tengo ningún contexto detrás de la respuesta. (Una de las muchas razones por las que las respuestas que son "solo un enlace" son malas)
