Idioma
Categoría
Buscar

TinyMCE: coloque el texto seleccionado dentro de un elemento span.

Configure un botón para colocar el texto seleccionado en el editor dentro de un elemento span que contiene una clase específica con las estilizaciones deseadas

En JavaScript Por Rudi Drusian Lange
Publicado el
Última actualización

La idea es configurar un botón para alternar entre agregar y quitar un span con un estilo css al texto seleccionado.

Este artículo utilizó la última versión de la serie 5, TinyMCE 5.10.9 y también la última versión disponible en esta fecha de la serie 6, TinyMCE 6.8.2.

Demo e Descarga

El contenido tratado en este artículo se puede probar en línea en nuestra demostración y también se puede descargar para uso local.

Demo Descargar 

Configuracion basica

Crea el <textarea> y carga TinyMCE:

HTML

<textarea id='default'></textarea>
<script src='tinymce.5.10.9/js/tinymce/tinymce.min.js'></script>

Cambie la ruta al archivo tinymce.min.js según su instalación.

Inicializando

Comenzaremos con un editor básico usando el elemento textarea con id='default' creado anteriormente. La altura se establecerá en 500px y el complemento code se cargará para que el código fuente esté disponible en HTML. La barra de herramientas se personalizará y contendrá botones en negrita, cursiva y código.

JavaScript

tinymce.init({
  selector: 'textarea#default',
  height: 500,
  plugins: 'code',
  toolbar: 'bold italic code',
  content_css: 'css/style.css?1',
  formats: {
     bold: {
        inline: 'span',
        attributes: { class: 'text-bold' },
	   },
	},
});

La opción content_css configura la ruta al archivo css que contiene las reglas de estilo que se utilizarán dentro del editor, por ejemplo para personalizar fuentes, párrafos y encabezados. Los caracteres ?1 delante del nombre del archivo css se utilizan para borrar el caché después de los cambios, cambiar el número delante del signo de interrogación obliga a recargar el archivo, esto ocurre porque se entiende que el nombre es diferente pero el archivo cargado es lo mismo.

Finalmente, cambiamos el comportamiento predeterminado de negrita, que consiste en envolver el texto seleccionado en un elemento <b>. Con la configuración anterior, al aplicar negrita, el texto seleccionado se envolverá en un elemento <span class='text-bold'> . En este caso, es necesario aplicar estilo a la negrita utilizando la clase text-bold en el archivo css.

CSS

.text-bold {
   font-weight: bold;
}

Pruebe el botón en negrita inspeccionando el código html del editor usando el botón < >.

Configurando los botones

Comenzando con CSS, prepare las clases que se utilizarán en el editor.

CSS

.text-bold { font-weight: bold; }
.text-red { color: red; }
.text-blue { color: blue; }

Recuerde cambiar el número al final de style.css?1 si realiza algún cambio en el CSS después de cargar el editor. TinyMCE almacena el caché y solo simulando el cambio en el nombre del archivo los cambios en el CSS tendrán efecto.

A continuación se muestra el código completo con dos botones adicionales, rojo y azul, que envuelven el texto seleccionado con un <span> que contiene sus respectivas clases CSS.

JavaScript

// Función para reemplazar caracteres HTML con sus entidades
function encodeHTML(s) {
   return s.replace(/&/g, '&amp;')
           .replace(/</g, '&lt;')
           .replace(/>/g, '&gt;')
           .replace(/"/g, '&quot;');
} 

tinymce.init({
  selector: 'textarea#default',
  height: 500,
  plugins: 'code',
  // Agrega botones rojo y azul a la barra de herramientas
  toolbar: 'bold italic code | textred textblue',
  content_css: 'css/style.css?1',
  formats: {
    bold: {
       inline: 'span',
       attributes: { class: 'text-bold' },
		},
    // Crea el formato para los botones
   'textred': {   inline: 'span',   classes: 'text-red',   wrapper: true   },   'textblue': {   inline: 'span',   classes: 'text-blue',     wrapper: true   }, }, setup: function(editor) {   // Función para colocar texto seleccionado dentro de un <span> // Recibe como parámetro la clase a utilizar en el <span> function wrapText(cls) {   const node = editor.selection.getNode();     const selectedText = encodeHTML(editor.selection.getContent({ format: 'text' }));   if (node.nodeName == 'SPAN') {     const l = node.classList.length;     if (l == 0) { node.classList.add(cls); } else if (l == 1) {     if (node.classList.contains(cls)) { editor.execCommand('mceReplaceContent', false, selectedText); } else { node.classList.add(cls); } } else { node.classList.remove(cls); } } else { editor.execCommand( 'mceReplaceContent', false, '<span class="' + cls + '">' + selectedText + '</span>'
);         } }   // Configurar los botones  editor.ui.registry.addButton('textred', {   text: 'Red',     tooltip: 'Red span',     onAction: function() {     wrapText('text-red'); } }); editor.ui.registry.addButton('textblue', {   text: 'Blue',   onAction: function() {     wrapText('text-blue'); } }); } });

En este ejemplo, se configuran dos botones adicionales para aplicar estilo al texto en el editor utilizando un elemento <span> que contiene una clase CSS. Seleccione el texto y haga clic en los nuevos botones para alternar la personalización.

Para eliminar la personalización, la selección debe contener exactamente el mismo texto que la selección original, incluido el espacio en blanco. Para alternar la personalización es necesario cambiar la posición del cursor en el editor antes de seleccionar el texto nuevamente. Consulte más información en la sección bugs a continuación.

Consideraciones finales

La función wrapText() envuelve el texto seleccionado en un <span> si aún no está en uno. Si el texto ya está rodeado por un <span> y no tiene la clase vinculada al botón, la clase se agregará al <span> en lugar de agregar un nuevo <span>.

Al pulsar en el botón, si el <span> que acompaña al texto tiene más de una clase, siendo una de ellas la clase vinculada al botón, esta será eliminada y el <span> se conservará con el resto de sus clases.

El <span> no se agregará si el cursor está posicionado sobre la palabra y el texto no está seleccionado.

Este artículo sirve de inspiración para otras situaciones, puedes agregar el texto en un <div>, crear botones para agregar plantillas, usar la creatividad.

Este es sólo un ejemplo con una funcionalidad sencilla, un punto de partida para una mayor personalización. Por lo tanto, la función wrapText() no tiene toda la lógica necesaria para evitar fallos. En algunas situaciones, los botones no funcionarán como se esperaba.

Bugs

Un error que parece estar relacionado con el editor ocurre de la siguiente manera: Al seleccionar texto y hacer clic en el botón negrita, se aplica el valor predeterminado, si hace clic en el botón Rojo inmediatamente después, el texto se volverá rojo y perderá su negrita. Para que funcione como debería, después de hacer clic en el botón negrita, cambie la posición del cursor, vuelva a seleccionar el texto y solo entonces haga clic en el botón Rojo, para que el texto esté en negrita roja.

Este mismo error ocurre al usar solo los botones nuevos. Si algo no funciona, intenta cambiar la posición del cursor y seleccionar el texto nuevamente. Si es solo una palabra, hacer doble clic funciona. Mover el cursor del teclado hacia adelante y hacia atrás y seleccionar nuevamente también funciona.

Referencias

El contenido de este artículo se escribió consultando la documentación en el sitio web de TinyMCE, los temas en el sitio web de stackoverflow y las preguntas formuladas a ChatGPT.

Este no es mi idioma original y no lo hablo muy bien. Utilicé mis pocos conocimientos y herramientas de traducción para redactar el texto de este artículo. Disculpe los posibles errores ortográficos o gramaticales, se agradecen sugerencias de correcciones y se pueden enviar al correo electrónico de contacto que se encuentra en el pie de página del sitio. Mi intención es compartir algunos conocimientos y espero que esta traducción sea lo suficientemente buena.