1

我有一个内容可编辑的 div。在此我插入一个<pre>some code</pre>标签。此标签旨在允许用户输入格式化代码,类似于 SO。

我遇到的问题是 FF 正在插入<br>标签来代替 \r\n,这在普通 Html 中是正确的,但在之前我实际上想要 \r\n。

我尝试将委托附加到父 contenteditable。但这不会触发嵌套的 dom 元素。所以

$('#contenteditablediv').delegate('pre', 'keyup', function() { ... });

不开火。我也尝试过处理父 div 上的正常键位,并将 pre 标签中的所有 brs 替换为 \r\n。但这会弄乱插入符号并且很笨重。

有这样做的首选方法吗?

我可能不得不诉诸于剥离它们的服务器端,但我宁愿不这样做。

非常感谢

4

2 回答 2

5

我实际上已经找到了解决方案。它并不完美,我正在考虑按照 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。

于 2011-07-27T01:55:42.573 回答
1

简单的答案:做服务器端。div 中的任何内容contentEditable都只是文本。因此,您delegate将永远不会开火。

我还建议查看可能已经处理所有这些的codemirror插件。

于 2011-07-27T01:05:24.393 回答