Rangy和IE8 - 在段落末尾的元素之后定位插入符号

时间:2012-07-27 09:26:10

标签: javascript internet-explorer-8 rangy

我正在使用Rangy在富文本编辑器中执行多项操作(designmode =“on”)。这些功能之一是粘贴格式化内容,该内容可以表示用户之前创建的某些预定义字符。所有文本内容都保存在段落元素中。用户可以从这开始:

<p>The following is a special character: |</p>

管道(|)是插入位置。然后,他们选择通过编辑器上的按钮粘贴其中一个“特殊”字符,最终得到:

<p>The following is a special character: <span class="read-only" contenteditable="false">SPECIAL</span>|</p>

该动作在幕后使用Rangy在内部粘贴过程中保持插入符号(SelectionSaveRestoreModule)的位置,该过程可以在编辑器中粘贴处理文本,否则可能会弄乱光标的位置。

然而,在IE8中,插入符号不能放在<span>之后,因为似乎存在一个使其成为无效位置的错误。结果,光标出现在<span>元素之前,甚至无法在使用键盘光标控制的跨度之后移动光标。实际上,它甚至会阻止光标移动到以下任何段落。

我最近几天尝试了几种技术,包括在<span>之后放置额外的字符并取得一些成功。然而,这些额外的字符显然会在用户出现时造成混淆并且不理想。使用零宽度空间在视觉上更好,但在粘贴操作导致问题后尝试整理它们。

我需要一种“整洁”的方法来支持特殊字符的用户要求,我自由地接受我可能会以错误的方式接近这一点。

1 个答案:

答案 0 :(得分:0)

到目前为止,我有一个似乎在我的测试中有效的解决方案,但是当我看到它时,它仍然让我觉得必须有更好的方法(更不用说恐惧感)。

此代码尝试执行的操作是在段落末尾的任何只读跨度之后放置零宽度空间。它通过检查这些元素之后的节点来确定它们中是否存在实际文本。同时,它删除了任何零宽度空间,这些空间可能仍然存在于以前不再需要的检查中。

var ZWS = '\ufeff';

jQuery(_doc.body).find('p').each(function () {
    var lastContentEditable = undefined;
    // Look through the root contents of each paragraph to remove no-longer require zws fixes
    jQuery(this).contents().each(function () {
         if (this.nodeType === 3) {
            if (this.nodeValue.indexOf(ZWS) != -1) {
                // Text node containing a ZWS - remove for now
                this.nodeValue = this.nodeValue.replace(new RegExp(ZWS, 'g'), '');
            }

            // Does this node now contain text?
            if (this.nodeValue.length > 0 && lastContentEditable) {
                // Found text after a read-only node, ergo we do not need to modify that read-only node at the end
                lastContentEditable = undefined;
            }
        } else if (this.nodeType === 1 && this.getAttribute('contenteditable') === "false") {
            // Indicate that this is currently the last read-only node
            lastContentEditable = this;
        }
    });

    if (lastContentEditable) {
        // It appears that there is a read-only element at the end of the paragraph.
        // Add the IE8 fix zws after it.
        var node = document.createTextNode(ZWS);
        jQuery(lastContentEditable).after(node);
    }

});