5

如果使用按钮,我可以轻松地对 contenteditable 选择执行 execcommand。但是,使用任何其他元素都会失败。

http://jsbin.com/atike/edit

为什么会这样以及如何使用 div 元素使其工作。

谢谢。

4

4 回答 4

11

您可以通过使用mousedown正在使用的元素上的事件而不是按钮来保存选择,并在关注事件中的可编辑元素后再次恢复它click

我修改了示例代码:http: //jsbin.com/atike/40/edit。这是代码:

function saveSelection() {
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            var ranges = [];
            for (var i = 0, len = sel.rangeCount; i < len; ++i) {
                ranges.push(sel.getRangeAt(i));
            }
            return ranges;
        }
    } else if (document.selection && document.selection.createRange) {
        return document.selection.createRange();
    }
    return null;
}

function restoreSelection(savedSel) {
    if (savedSel) {
        if (window.getSelection) {
            sel = window.getSelection();
            sel.removeAllRanges();
            for (var i = 0, len = savedSel.length; i < len; ++i) {
                sel.addRange(savedSel[i]);
            }
        } else if (document.selection && savedSel.select) {
            savedSel.select();
        }
    }
}

$(function() {
  var savedSel;

  $('.bold').mousedown(function () {
    savedSel = saveSelection();
  });

  $('.bold').click(function () {
    $('#hello').focus();
    if (savedSel) {
      restoreSelection(savedSel);
    }
    document.execCommand("bold", false, null);    
  });
});
于 2011-04-14T14:29:38.743 回答
1

大多数(如果不是全部)所见即所得的编辑器都使用一个iframe元素来避免丢失选择。另一种方法(虽然我没有尝试过)是在mouseup事件触发后存储在该页面上所做的每个选择。

看看这个关于Midas的页面,Gecko 的内置富文本编辑器。

于 2009-09-26T23:24:51.323 回答
1

发生的情况是,当您单击文本节点时,浏览器想要选择该文本。按钮不是文本流的一部分,因此不会触发新的选择。

您所要做的就是阻止浏览器执行重新选择。当click您当前正在观察的事件运行时,选择已经发生并且为时已晚。该动作开始发生在mousedown除 MSIE 之外的所有浏览器上,它具有特殊的选择事件。

这适用于我的浏览器:

jQuery('.bold')
  .attr('unselectable','on') // prevents selection in MSIE
  .bind('mousedown',function (e) {
    document.execCommand("bold", false, null);
    e.preventDefault(); // prevents selection in all but MSIE
  });

使用 MSIE 的选择事件有一些复杂性(例如还必须阻止拖动),因此只需使用专用属性unselectable(需要值“on” )取消您用作按钮的元素的可选择性更容易)。

您显然仍然可以execCommand在事件中执行处理click,只需在所有作为“按钮”的元素上运行选择预防代码:

jQuery('.buttonlike')
  .attr('unselectable','on') // prevents selection in MSIE
  .bind('mousedown',function (e) {
    e.preventDefault(); // prevents selection in all but MSIE
  });

jQuery('#edit-bold').click(function(){
  document.execCommand("bold", false, null);
});
于 2011-04-15T12:11:51.343 回答
0

NicEdit使用多种方法。

  • 大多数工具栏元素都设置了“不可选择”属性 - 这适用于 Internet Explorer。

  • 在相同的元素上,它注册“mousedown”事件并覆盖默认操作 - 这会阻止文本解决方案和焦点。这仅适用于 IE 以外的浏览器。

  • 一些工具栏元素需要能够接收文本焦点并进行选择,例如用于插入链接或图像的字段。对于这些,它会在编辑器失去焦点之前保存选择,然后在用户完成编辑并需要进行更改后恢复它。

    有关如何实现它,请查看 NicEdit 的代码。搜索函数名称:

    • 获取选择
    • 获取
    • 销售
    • 保存
    • 恢复

    ...

    这使用浏览器的 getSelection() 或 document.selection 来获取选择,getRangeAt() 将其转换为范围,并使用 addRange() 或 select() 将该范围恢复为选择。

于 2011-04-14T00:39:22.883 回答