<pre> inside content editable, replace <br/> with \r\n</pre>

时间:2011-07-27 00:04:59

标签: jquery contenteditable rangy

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

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

我已尝试将委托附加到父级contenteditable。但这并没有触发嵌套的dom元素。所以

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

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

有没有首选的方法呢?

我可能不得不求助于剥离服务器端,但我宁愿不这样做。

非常感谢

2 个答案:

答案 0 :(得分:4)

我实际上找到了一个解决方案。这并不完美,我正在考虑像Mrchief所建议的那样整合codemirror。唯一的问题是我当前的解决方案允许我编辑将保存在后端并稍后显示的标记。这是真正的所见即所得。我应该提到我的编辑器是一篇更令人满意的文章的一部分,我想在其中添加一些代码片段。

使用像codemirror这样的编辑器会很棒但是Id必须在保存之前将其删除,并且我的代码块必须显示为textarea(而不是像以前那样友好的RSS)。

无论如何,任何对此感兴趣的人都是我的解决方案/黑客。


只要将事件包含在<pre>的元素中,您就可以委托嵌套contenteditable="false"标记等事件在contenteditables中进行委派。所以不要插入:

<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');
    });

此事件触发。我添加了一个点击/模糊删除来切换内部预标记上的contenteditable,这样就不会在之后保存,但可以在服务器端完成。这允许我在tab键和\ r \ n上插入\ t字符代替br。

答案 1 :(得分:1)

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

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