Renderizando HTML dentro da área de texto

146

Eu preciso ser capaz de renderizar algumas tags HTML dentro de uma área de texto (ou seja, <strong>, <i>, <u>, <a>), mas as áreas de texto apenas interpretam seu conteúdo como texto. Existe uma maneira fácil de fazer isso sem depender de bibliotecas / plugins externos (estou usando o jQuery)? Caso contrário, você conhece algum plugin jQuery que eu poderia usar para fazer isso?

O Monge Codificador
fonte
A única maneira de fazer isso será sobrepor sua marcação HTML sobre o conteúdo da tag textarea por meio de truques de posicionamento CSS. Nada o ajudará a convencer o navegador a renderizar o conteúdo da área de texto de maneira diferente. (Por que exatamente você "necessidade" de fazer isso?)
Pointy
Eu só preciso que o usuário possa adicionar alguns estilos de formatação ao texto que ele digita (assim como quando você escreve um artigo no Wordpress). Só não preciso de todos os recursos, como alinhamento de texto e assim por diante, mas apenas dessas tags básicas.
A codificação Monk

Respostas:

234

Isso não é possível com a textarea. O que você está procurando é uma div editável de conteúdo , que é feita com muita facilidade:

<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
fonte
8
é uma pena que você praticamente não possa usar isso sem o uso de javascript para enviar suas alterações usando ajax ou copiá-las em uma entrada de formulário. Se alguém encontrou uma maneira de fazê-lo, eu estaria realmente interessado!
Ben
3
@ yckart: Bem, eu não acho que isso seja realmente válido, mesmo que funcione em todos os navegadores que eu tentei. contenteditableé um atributo enumerado, em vez de um atributo booleano (há um inheritestado, além de truee false), e acho que isso significa que especificar um valor é obrigatório, embora não seja possível encontrar um bit definitivo da especificação para confirmar isso. MDN parece concordar embora.
Tim Baixo
2
@ yckart: Eu assumi que o navegador interpreta contenteditablesem valor como sendo o mesmo que contenteditable="", por sua vez, é o mesmo que contenteditable="true".
Tim Baixo
7
Isso não funciona melhor do que a textarea. Digitar <strong>someting</strong>o violino deixa você com o texto exato. O HTML não é aplicado.
Matt Ellen
2
@ MarcusEkwall mas não era a pergunta pedindo renderização em html?
phil294
31

Com uma div editável, você pode usar o método document.execCommand( mais detalhes ) para fornecer facilmente o suporte para as tags que você especificou e para outras funcionalidades.

#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
fonte
Isso não funciona em alguns navegadores, apenas adicionando isso como uma nota AS 'de 16
jeffrey crowder 03/12/16
5

Desde que você disse apenas render, sim você pode. Você pode fazer algo como:

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>
Isso faz com que a textarearenderize html! Além de piscar ao redimensionar, incapacidade de usar classes diretamente e ter que garantir que a div no svgtenha o mesmo formato que textareao cursor para alinhar corretamente, funciona!

Merlin
fonte
2

Um adendo a isso. Você pode usar entidades de caracteres (como alterar <div>para &lt;div&gt;) e elas serão renderizadas na área de texto. Mas quando é salvo, o valor da área de texto é o texto renderizado . Portanto, você não precisa decodificar. Acabei de testar isso nos navegadores (ou seja, de volta ao 11).

axlotl
fonte
Eu realmente gostaria que isso funcionasse para mim, mas não funcionou. Por exemplo, <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>não é exibido como HTML. Estou no Chrome 46.
sirdank
Hum. Copiei e colei essa sequência diretamente em um documento html e ela renderiza a marcação corretamente para mim no OS X 10.11.1 do Chrome Versão 48.0.2552.0 dev (64 bits). Então talvez seja um problema de versão.
axlotl
Recebo down-votou neste então aqui está uma caneta: codepen.io/axlotl/pen/YGZOEq
axlotl
0

Eu tenho o mesmo problema, mas ao contrário, e a seguinte solução. Quero colocar o html de uma div em uma área de texto (para que eu possa editar algumas reações no meu site; eu quero ter a área de texto no mesmo local.)

Para colocar o conteúdo dessa div em uma área de texto, eu 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
fonte
0

tente este exemplo

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
fonte
-2

Isso é possível com <textarea> a única coisa que você precisa fazer é usar o editor Summernote WYSIWYG

ele interpreta tags HTML dentro de uma textarea (ou seja <strong>, <i>, <u>, <a>)

Fenil Shah
fonte
Não usa área de texto. Ele usa div, que não pode ser enviado com um formulário.
precisa saber é o seguinte
Ele funciona com a área de texto, apenas tente dar id à área de texto em vez de div. Criei um projeto inteiro usando textarea e summernote. Funciona bem!
Fenil Shah
Qual é o objetivo? Ele se comporta da mesma forma que o ckeditor se a área de texto for usada. Não é possível renderizar tags HTML conforme solicitado.
precisa saber é o seguinte
Por que devo usar um editor WYSIWYG? Isso realmente não é uma resposta, desculpe.
Luca De Nardi