我实际上已经找到了解决方案。它并不完美,我正在考虑按照 Mrchief 的建议集成codemirror。唯一的问题是我当前的解决方案允许我编辑将保存在后端并稍后显示的标记。它是真正的所见即所得。我应该提到我的编辑器是一篇内容更丰富的文章的一部分,我想在其中添加一些代码片段。
使用像 codemirror 这样的编辑器会很棒,但是我必须在保存之前将其删除,并且我的代码块必须显示为 textarea(不像 pre 那样对 RSS 友好)。
无论如何,对这里感兴趣的人来说,我的解决方案/hack。
您可以在 contenteditables 中委托来自嵌套<pre>
标签等的事件,只要它们包含在带有contenteditable="false"
. 所以不要插入:
<pre>some code</pre
我插入:
<code contenteditable="false"><pre>code snippet here</pre></code>
然后我像这样添加了一个代表。
var getFirstRange = function() {
var sel = rangy.getSelection();
return sel.rangeCount ? sel.getRangeAt(0) : null;
}
contenteditablediv
.delegate('pre', 'keydown', function(event) {
switch(event.keyCode) {
case 13:
var range = getFirstRange(),
added = false,
newline = document.createTextNode('\r\n');
if (range) {
range.insertNode(newline);
range.setEndAfter(newline);
range.setStartAfter(newline);
var sel = rangy.getSelection();
sel.setSingleRange(range)
added = true;
}
if (added) {
event.preventDefault();
}
break;
case 9:
// insert a tab
var range = getFirstRange(),
tab = document.createTextNode('\t');
if (range) {
range.insertNode(tab);
var sel = rangy.getSelection();
range.setEndAfter(tab);
range.setStartAfter(tab);
sel.setSingleRange(range)
}
return false;
}
}).delegate('pre', 'click', function() {
$(this).attr('contenteditable', true);
}).delegate('pre', 'blur', function() {
$(this).removeAttr('contenteditable');
});
此事件触发。我添加了一个单击/模糊删除来切换内部 pre 标记上的 contenteditable,因此这不会在之后保存下来,但可以在服务器端完成。这允许我在制表键上插入 \t 字符,并用 \r\n 代替 br。