如何在contentEditable范围内进行纯文本粘贴而不破坏撤消?

时间:2011-02-23 03:28:58

标签: javascript jquery webkit contenteditable

奇怪的具体问题,但我已经有一个解决方案已经通过使用隐藏的<span contentEditable="true">textarea中粘贴纯文本,这看起来效果很好,除了它打破了浏览器的撤消功能。马上,我并不担心跨浏览器解决方案;我只关心Chrome。我的方法大致如下:

$('.editable').live('paste', function()
{
    var $this = $(this);

    //more code here to remember caret position, etc

    $('#clipboard').val('').focus(); //put the focus in the hidden textarea so that, when the paste actually occurs, it's auto-sanitized by the textarea

    setTimeout(function() //then this will be executed immediately after the paste actually occurs
    {
        $this.focus();
        document.execCommand('insertHTML', true, $('#clipboard').val());
    });
});

所以这样做 - 我可以粘贴任何内容,并且在进入我的contentEditable字段之前将其缩小为纯文本 - 但是如果我在粘贴后尝试撤消:

  • 首先撤消取消粘贴。
  • 第二次撤消尝试撤消对#clipboard的更改,将焦点从contentEditable移开。

我已经尝试了一切我能想到的事情,让浏览器不要尝试撤消对#clipboard的更改 - 切换display:none当它没有正在使用时,切换readonlydisabled状态,在上面的事件开始时摧毁它并在上面的事件开始时重新创建它,各种其他黑客 - 但似乎没有任何效果。

这是一种可怕的消毒方法吗?这是我设法真正开始工作的第一件事 - 在粘贴发生后尝试清理标记不起作用,因为有些东西(整个HTML文档)在粘贴时会崩溃浏览器,我想避免。

有没有办法让#clipboard无法撤消,或者其他任何有关如何使其发挥作用的建议?

修改

我设法通过添加行

来改善一些事情
$('#clipboard').val('');

execCommand行之后。这似乎完全抵消了撤销:插入符号不再离开contentEditable字段,但根本没有任何撤消。有点改进,但​​我仍在寻找合适的解决方案。

4 个答案:

答案 0 :(得分:1)

CodeMirror 1通过在粘贴文本后剥离格式来完成此操作。 CodeMirror 2通过实际拥有一个不可见的textarea来处理所有内容,并手动渲染文本和光标。

CodeMirror的网站更详细地描述了它的工作原理:http://codemirror.net/internals.html

除此之外,始终存在CodeMirror源代码。您可以自己决定CodeMirror 1或CodeMirror 2的方法是否更适合您的用途。 :)

答案 1 :(得分:0)

你试试吗?

setTimeout(function() //then this will be executed immediately after the paste actually occurs
{
    $this.focus();
    document.execCommand('insertHTML', true, $('#clipboard').val());
    var t = document.body.innerHTML;
    document.execCommand("undo");
    document.body.innerHTML = t;
});

我认为它可以提供帮助。 但我认为你必须使用事件对象。不幸的是,出于安全原因可能存在问题。

答案 2 :(得分:0)

在onpaste:

  1. 存储当前选择。

    var sel = window.getSelection();
    var range  = selObj.getRangeAt(0).cloneRange;
    // Store the range object somewhere.
    
  2. 修改选择对象以指向隐藏的文本区域。

  3. 设置延迟时间为0(粘贴后立即发生)。

  4. 在超时功能中,从隐藏的textarea中获取数据,然后:

    var sel = window.getSelection();
    sel.removeAllRanges();
    var range = // restore the range object from before.
    sel.addRange(range);
    
    document.execCommand("insertHTML", false, /* contents of your textarea here */);
    
  5. 现在,如果你想为实际的HTML内容做这件事,那么你将处于一个受伤的世界......

答案 3 :(得分:-2)

插入<pre contenteditable="true">...</pre>。我记得这正是我理解你想要的。 (不幸的是我还没有被允许加入评论中的每个人,但我想这无论如何都是试图回答。)