Un editor de texto con javaScript (1)

Ahora es muy fácil crear un editor de texto con javaScript.

Lampika

archivado en: JavaScript / 21 agosto, 2014

Hay dos editores de texto WYSIWYG muy buenos realizados con HTML y JavaScript, el CKEditor y el tinyMCE. Además, si necesitamos algo mucho más ligero, también tenemos a nuestra disposición el bootstrap-wysiwyg y otros similares; pero en este post vamos a ver cómo podemos programar uno desde cero de forma muy sencilla y divertida gracias al atributo contenteditable de HTML y el método execCommand() del objeto document de javaScript. El atributo contenteditable puede tomar dos valores, true o false, y si está en true hace que el contenido de ese tag se pueda editar, es decir, que al ser pulsado, el usuario pueda modificar su contenido mediante el teclado y el ratón.

<div id="editorWYS" contenteditable="true">

Lo que hay dentro de este div se puede editar.

</div>

Ahora, podemos añadir un botón que al ser pulsado ponga el texto seleccionado en negrita mediante el método execComand. El botón, pasado por las CSS de Bootstrap, puede ser algo así:
<button class="js-boton" data-type="bold"><span class="glyphicon glyphicon-bold"></span></button>
Y el script algo como esto:
$(document).ready(function() {

$(".js-boton").mousedown(function(event) {

document.execCommand('bold', false, null);

});

})

document.execCommand acepta tres parámetros, en el primero indicamos qué comando queremos ejecutar, en este caso, negrita (bold); en el segundo, si vamos a usar una interfaz de usuario, algo que todavía está muy verde, por lo que lo dejamos en false, y en el tercero indicamos algunos datos adicionales que necesitan algunos comandos, como una url. Como en este caso no lleva ninguno, lo definimos como null. Hay una montonera de comandos, que no tiene sentido repetir aquí pues están muy bien documentados, por lo que me limito a mostrar cómo armar una botonera sencilla: en un atributo data definimos el comando y luego lo recuperamos y se lo enviamos a execCommand. Algo así en el html:

<button class="js-boton" data-type="bold"><span class="glyphicon glyphicon-bold"></span></button>

<button class="js-boton" data-type="italic"><span class="glyphicon glyphicon-italic"></span></button>

<button class="js-boton" data-type="justifyLeft"><span class="glyphicon glyphicon-align-left"></span></button>

<button class="js-boton" data-type="justifyCenter"><span class="glyphicon glyphicon-align-center"></span></button>

<button class="js-boton" data-type="justifyRight"><span class="glyphicon glyphicon-align-right"></span></button>

<div id="editorWYS" contenteditable="true"> Lo que hay dentro de este div se puede editar. </div>

y algo así en el js.

$(document).ready(function() {

$(".js-boton").mousedown(function(event) {

event.preventDefault(); // Esto no es necesario, es por vicio xD

var comando = $(this).attr('data-type');

document.execCommand(comando, false, null);

});

});

ver demo en plunker

Bueno, espero que hasta aquí todo esté claro, veamos ahora qué ocurre cuando perdemos el foco del nodo en el que hemos seleccionado algo.

Botones sin foco (dialogs)

En el caso anterior he utilizado el evento mousedown() en vez de un click() para que no se pierda el foco y con este, la selección del texto. Es un truco sencillo, pero se queda corto cuando no nos queda más remedio que perder el foco, como ocurre cuando necesitamos abrir un dialog o similar para que el usuario introduzca datos. En estas situaciones, el truco es primero guardar la selección y, después de que se hayan trabajado los datos pertinentes, restaurarla antes de ejecutar el execCommand. Un caso típico es un botón para insertar un enlace, donde no nos queda más remedio que incorporar un input para que se ponga la url. Vamos a ver cómo hacerlo :P. Primero añadimos un div a nuestro editor que nos servirá de dialog y un botón que lo abre:

 

<div id="js-dialog" style="display:none;"></div>

<button class="js-boton" data-type="bold">

<span class="glyphicon glyphicon-bold"></span></button> ...

<button id="js-enlaces"><span class="glyphicon glyphicon-paperclip"></span></button>

<div id="editorWYS" contenteditable="true"> </div>

Luego, en el js incorporamos tres funciones como las que tiene el bootstrap-wysiwyg, que están muy bien pensadas. Sin entrar en detalles, basta con decir que se basan en el método getSelection(), que recoge lo que está seleccionado: 

var selectedRange;

function getCurrentRange() {

var sel = window.getSelection();

if (sel.getRangeAt && sel.rangeCount) {

return sel.getRangeAt(0);

}

}

function saveSelection() {

selectedRange = getCurrentRange();

}

function restoreSelection() {

var selection = window.getSelection();

if (selectedRange) {

try {

selection.removeAllRanges();

} catch (ex) {

document.body.createTextRange().select();

document.selection.empty();

}

selection.addRange(selectedRange);

}

}

Y ahora solo necesitamos incorporar la funcionalidad del botón enlace:

$('#js-enlaces').mousedown(function(event) {

var cadena;

saveSelection();

cadena = "<div id='js-bodyDialog'>";

cadena += "<input type='text' id='js-inputURL' /><br />";

cadena += "<button id='js-aceptar'>Aceptar</button>";

cadena += "<button id='js-cancelar'>Cancelar</button>";

cadena += "</div>";

$('#js-dialog').html(cadena).show();

 

$('#js-cancelar').click(function() {

$('#js-bodyDialog').remove();

$('#js-dialog').hide();

});

$('#js-aceptar').click(function(event) {

event.preventDefault();

var href = $('#js-inputURL').val().trim().toLowerCase();

restoreSelection();

document.execCommand("createLink", false, href);

$('#js-bodyDialog').remove();

$('#js-dialog').hide();

});

});

ver demo en plunker

Bueno, pues con esto y los métodos habituales de jQuery para trabajar el DOM, más o menos tenemos todo lo necesario para hacer un editor de texto con javaScript. Otro día vemos cómo incorporar otras funcionalidades, como un corrector de texto o un modo de visualización de código, y cómo enviar el texto editado por ajax a algún lado, pero por hoy lo dejo aquí :P.

Adenda

Otro día explico esto mejor. El método anterior tiene el inconveniente de que el texto que se devuelve es plano, sin código html; por lo que puede ser mejor hacer algo así en algunos casos:

$("#js-botonVersalitas").mousedown(function(event) {

var selObj = window.getSelection();

var selRange = selObj.getRangeAt(0);

var newNode = document.createElement("span");

newNode.style.cssText = 'font-variant:small-caps;';

selRange.surroundContents(newNode);

});

|| Tags: , , ,

valoración de los lectores sobre Un editor de texto con javaScript (1)

  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • 5 sobre 5 (7 votos)

¿Te ha parecido útil o interesante esta entrada?
dormido, valoración 1 nadapensativo, valoración 2 un poco sonrisa, valoración 3 a medias guiño, valoración 4 bastante aplauso, valoración 5 mucho

Tú opinión es muy importante, gracias por compartirla!

4 respuestas a “Un editor de texto con javaScript (1)

  1. johnny el dijo:

    muchas, gracias me sirvio de mucha utilidad, me gustaria que hicieras otro post, ampliando este tema, agregando nuevas funciones.