Renderizar HTML dentro de textarea

146

Necesito poder representar algunas etiquetas HTML dentro de un área de texto (es decir, <strong>, <i>, <u>, <a>) pero las áreas de texto solo interpretan su contenido como texto. ¿Hay una manera fácil de hacerlo sin depender de bibliotecas / complementos externos (estoy usando jQuery)? Si no, ¿conoce algún complemento jQuery que pueda usar para hacer esto?

El monje codificador
fuente
La única forma de hacerlo será superponer su marcado HTML sobre el contenido de la etiqueta textarea mediante trucos de posicionamiento CSS. Nada lo ayudará a convencer al navegador para que represente los contenidos del área de texto de manera diferente. (¿Por qué exactamente "necesitas" hacer esto?)
Puntiagudo
Solo necesito que el usuario pueda agregar algunos estilos de formato al texto que ingresa (al igual que cuando escribe un artículo en Wordpress). Simplemente no necesito todas las funciones, como la alineación de texto, etc., sino solo esas etiquetas básicas.
The Coding Monk

Respuestas:

234

Esto no es posible hacer con a textarea. Lo que está buscando es un contenido editable div, que se hace muy fácilmente:

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

jsFiddle

div.editable {
    width: 300px;
    height: 200px;
    border: 1px solid #ccc;
    padding: 5px;
}

strong {
  font-weight: bold;
}
<div contenteditable="true">This is the first line.<br>
See, how the text fits here, also if<br>there is a <strong>linebreak</strong> at the end?
<br>It works nicely.
<br>
<br><span style="color: lightgreen">Great</span>.
</div>

Mekwall
fuente
8
es una verdadera lástima que prácticamente no puedas usar esto sin el uso de javascript para enviar tus cambios usando ajax o copiarlos en una entrada de formulario. Si alguien ha encontrado una manera de hacerlo, ¡estaría realmente interesado!
Ben
3
@yckart: Bueno, no creo que sea realmente válido, a pesar de que funciona en todos los navegadores que he probado. contenteditablees un atributo enumerado en lugar de un atributo booleano (hay un inheritestado así como truey false), y creo que eso significa que especificar un valor es obligatorio, aunque no puedo encontrar un bit definitivo de la especificación para confirmar esto. MDN parece estar de acuerdo sin embargo.
Tim Down
2
@yckart: asumí que el navegador interpreta contenteditablesin valor que es el mismo contenteditable="", que a su vez es el mismo contenteditable="true".
Tim Down
77
Esto no funciona mejor que a textarea. Escribir <strong>someting</strong>en el violín te deja con ese texto exacto. El HTML no se aplica.
Matt Ellen
2
@ MarcusEkwall, pero ¿no era la pregunta que pedía la representación html?
phil294
31

Con un div editable, puede usar el método document.execCommand( más detalles ) para proporcionar fácilmente el soporte para las etiquetas que especificó y para alguna otra funcionalidad.

#text {
    width : 500px;
	min-height : 100px;
	border : 2px solid;
}
<div id="text" contenteditable="true"></div>
<button onclick="document.execCommand('bold');">toggle bold</button>
<button onclick="document.execCommand('italic');">toggle italic</button>
<button onclick="document.execCommand('underline');">toggle underline</button>

Sampath Liyanage
fuente
Esto no funciona en algunos navegadores simplemente agregando esto como una nota a partir de '16
jeffrey crowder
5

Como solo dijiste render, sí puedes. Podrías hacer algo en este sentido:

function render(){
	var inp     = document.getElementById("box");
	var data = `
<svg xmlns="http://www.w3.org/2000/svg" width="${inp.offsetWidth}" height="${inp.offsetHeight}">
<foreignObject width="100%" height="100%">
<div xmlns="http://www.w3.org/1999/xhtml" 
style="font-family:monospace;font-style: normal; font-variant: normal; font-size:13.3px;padding:2px;;">
${inp.value} <i style="color:red">cant touch this</i>
</div>
</foreignObject>
</svg>`;
	var blob = new Blob( [data], {type:'image/svg+xml'} );
	var url=URL.createObjectURL(blob);
	inp.style.backgroundImage="url("+URL.createObjectURL(blob)+")";
 }
 onload=function(){
  render();
  ro = new ResizeObserver(render);
	ro.observe(document.getElementById("box"));
 }
#box{
  color:transparent;
  caret-color: black;
  font-style: normal;/*must be same as in the svg for caret to align*/
  font-variant: normal; 
  font-size:13.3px;
  padding:2px;
  font-family:monospace;
}
<textarea id="box" oninput="render()">you can edit me!</textarea>
¡Esto hace que a textarearenderice html! Además del parpadeo al cambiar el tamaño, la incapacidad de usar clases directamente y tener que asegurarse de que el div en el svgtiene el mismo formato que el textareadel cursor para alinearse correctamente, ¡funciona!

esmerejón
fuente
2

Una adición a esto. Puede usar entidades de caracteres (como cambiar <div>a &lt;div&gt;) y se representará en el área de texto. Pero cuando se guarda, el valor del área de texto es el texto tal como se representa . Por lo tanto, no necesita descodificar. Acabo de probar esto en los navegadores (es decir, volver a 11).

axlotl
fuente
Realmente me gustaría que esto funcionara para mí, pero no fue así. Por ejemplo, <textarea> check for url &lt;B&gt;http://localhost/Dashboard.aspx&lt;/B&gt; &lt;BR&gt; Tool Started at &lt;B&gt;11/10/2015 3:56:58 AM&lt;/B&gt; &lt;BR&gt; .... </textarea>no se muestra como HTML. Estoy en Chrome 46.
sirdank
Hm. Copié y pegué esa cadena directamente en un documento html y me muestra el marcado correctamente en Chrome Versión 48.0.2552.0 dev (64 bits) OS X 10.11.1. Entonces quizás sea un problema de versión.
axlotl
Sigo siendo rechazado por esto, así que aquí hay una pluma: codepen.io/axlotl/pen/YGZOEq
axlotl
0

Tengo el mismo problema pero a la inversa, y la siguiente solución. Quiero poner html desde un div en un área de texto (para poder editar algunas reacciones en mi sitio web; quiero tener el área de texto en la misma ubicación).

Para poner el contenido de este div en un área de texto que uso:

var content = $('#msg500').text();
$('#msg500').wrapInner('<textarea>' + content + '</textarea>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="msg500">here some <strong>html</strong> <i>tags</i>.</div>

Houdini
fuente
0

prueba este ejemplo

function toggleRed() {
  var text = $('.editable').text();
  $('.editable').html('<p style="color:red">' + text + '</p>');
}

function toggleItalic() {
  var text = $('.editable').text();
  $('.editable').html("<i>" + text + "</i>");
}

$('.bold').click(function() {
  toggleRed();
});

$('.italic').click(function() {
  toggleItalic();
});
.editable {
  width: 300px;
  height: 200px;
  border: 1px solid #ccc;
  padding: 5px;
  resize: both;
  overflow: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="editable" contenteditable="true"></div>
<button class="bold">toggle red</button>
<button class="italic">toggle italic</button>

david grinstein
fuente
-2

Esto es posible con <textarea> lo único que debe hacer es usar el editor WYSIWYG de Summernote

interpreta etiquetas HTML dentro de un área de texto (es decir <strong>, <i>, <u>, <a>)

Fenil Shah
fuente
No usa textarea. Utiliza div, que no se puede enviar con un formulario.
Usman Ahmed
Funciona con textarea, solo intente dar id a textarea en lugar de div. Creé un proyecto completo usando textarea y summernote. ¡Funciona bien!
Fenil Shah
¿Cuál es el punto de? Se comporta igual que ckeditor si se usa textarea. No se pueden procesar etiquetas HTML como se le solicitó.
Usman Ahmed
¿Por qué debería usar un editor WYSIWYG? Esto realmente no es una respuesta, lo siento.
Luca De Nardi