在文本域中呈现HTML

192

我需要在文本域内呈现一些HTML标签(即<strong>,<i>,<u>,<a>),但是文本域只将其内容解释为文本。是否有简单的方法可以在不依赖外部库/插件(我正在使用jQuery)的情况下完成? 如果没有,您知道我可以使用哪个jQuery插件来完成吗?


唯一的方法是通过CSS定位技巧将HTML标记覆盖在textarea标签的内容上。没有任何方法可以说服浏览器以不同的方式呈现textarea的内容。(为什么你“需要”这样做呢?) - Pointy
我只需要用户能够为输入的文本添加一些格式样式(就像在WordPress上撰写文章时那样)。我只需要基本标签,而不需要所有的功能,例如文本对齐等。 - The Coding Monk
对于加粗和斜体,您可以将Unicode字符拼凑在一起,例如:,,,。换句话说,您需要一个替换输入中这些字符的函数。还应该有下划线和删除线的Unicode字符。 - Avatar
7个回答

297

使用 textarea 是无法实现这个功能的。您需要使用 contentEditable 属性来替代, 实现起来非常简单:

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


10
如果没有使用JavaScript通过AJAX提交更改或将更改复制到表单输入框中,实际上你无法使用它,这真是遗憾。如果有人找到了解决方法,我会非常感兴趣! - Ben
3
@yckart:尽管我在所有我尝试的浏览器中都可以使用,但我认为那并不是有效的,因为contenteditable是一个枚举属性,而不是布尔属性(除了truefalse状态外还有一个inherit状态)。我认为这意味着指定一个值是必需的,尽管我无法找到明确的规范部分来确认这一点。然而,MDN似乎也持相同看法。 - Tim Down
2
@yckart:我原以为浏览器会将没有值的contenteditable解释为与contenteditable =""相同,而后者又与contenteditable="true"相同。 - Tim Down
7
这不比“文本区域”好用。在代码编辑器中输入“<strong>someting</strong>”,得到的将是这个准确的文本,HTML 标签未被解析。 - Matt Ellen
3
但是问题不是在问HTML渲染吗? - phil294
显示剩余12条评论

39
使用可编辑div,您可以使用方法 document.execCommand 更多详细信息)轻松提供您指定的标签和其他功能的支持...

#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>


2
这在某些浏览器中无法正常工作,只是加注释于'16。 - jeffrey crowder
截至2020年,使用率为96%。 (https://caniuse.com/?search=document.execCommand) - ogostos
这真是太棒了 - 简直太棒了 - 为我节省了大量的工作! - Martin Meeser
2
看起来它已经被弃用了 - 真遗憾 - Martin Meeser

10

Since you only said render, yes you can. You could do something along the lines of this:

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>

This makes it so that a textarea will render html! Besides the flashing when resizing, inability to directly use classes and having to make sure that the div in the svg has the same format as the textarea for the caret to align correctly, it's works!


有趣的方法!从没想过SVG图形会在这里派上用场。但是当你在文本中添加<时就会出现问题。 - Avatar
@Avatar 虽然为了简单起见,我在这个例子中没有展示它,但你可以开发一个自定义文本解析器来处理它。这样加上绘制文本光标而不是默认的 Web 光标,将使您更轻松地进行自定义文本。例如,您目前可以粘贴 <b>hello</b> 来获得粗体文本。 添加自定义文本解析器,其可能性是无限的。例如,您可以使每个 a 字符变成红色。如果您愿意,我可以看看我以前做过的更详细的版本。 - merlin
1
@Avatar 我找到了,但我已经不知道它到底是做什么的了(我认为它通过在字符上方绘制线条来制作Ascii艺术)。https://jsbin.com/lacobib/3/edit?html,css,js,output - merlin
谢谢提供链接。这很高级,也许将来我会尝试实现。 - Avatar

4

尝试这个示例:

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>


3
只对部分文本应用样式怎么办? - ogostos
它应该做什么?它的要点是什么? - Peter Mortensen

3
补充一下:您可以使用字符实体(例如将<div>更改为&lt;div&gt;),它将在文本区域中呈现。
但是,当保存时,文本区域的值是渲染后的文本。因此,您不需要进行解码。我刚在各个浏览器上测试了这一点(从Internet Explorer 版本11开始)。

我真的很希望这对我有用,但它没有。例如<textarea>检查url &lt;B&gt;http://localhost/Dashboard.aspx&lt;/B&gt;&lt;BR&gt;工具启动于&lt;B&gt;2015年11月10日上午3:56:58&lt;/B&gt;&lt;BR&gt;....</textarea>不会显示为HTML。我使用的是Chrome 46。 - sirdank
嗯,我直接将该字符串复制粘贴到 HTML 文档中,在 Chrome 版本 48.0.2552.0 dev(64 位)OS X 10.11.1 中会正确渲染标记,所以可能是版本问题。 - axlotl
我一直因为这个而被踩,所以给你一个链接:http://codepen.io/axlotl/pen/YGZOEq - axlotl
如果你输入 <i> test <i>,它会显示为斜体吗?不会!但这就是“渲染”的意思。 - Martin Meeser

0
我有相同的问题,但是相反的情况,并且有以下解决方案。我想将一个 div 中的 html 放入 textarea 中(这样我就可以编辑网站上的一些反应;我希望 textarea 在同一位置)。
为了将此 div 的内容放入 textarea 中,我使用:

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>


-3

使用<textarea>可以实现这一点。您只需要使用Summernote所见即所得编辑器

它可以在文本区域内解释HTML标记(即<strong><i><u><a>)。


它不使用文本区域。它使用 div,无法与表单一起提交。 - Usman Ahmed
它可以与文本区域一起使用,只需尝试为文本区域提供ID而不是DIV即可。 我使用了文本区域和Summernote创建了整个项目。它运行良好! - Fenil Shah
有什么意义呢?如果使用文本区域,它的行为与 ckeditor 相同。无法按要求呈现 HTML 标记。 - Usman Ahmed
为什么我应该使用所见即所得编辑器?这真的不是一个答案,抱歉。 - Luca De Nardi
它不使用文本区域。不是一个答案。 - Rahul Gandhi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接