使用jQuery拆分包含TextNodes和元素的元素

6
我需要使用jQuery根据用户的选择来分割HTML元素。在以下示例中,方括号表示所选内容:
Lor[em <a>ips]um <span>dolor</span></a>

应该变成

Lor [ em <a>ips</a> ] <a>um <span>dolor</span></a>

为了做到这一点,我创建了一个范围,找到包含选择边界的TextNodes并使用splitText(index)将它们拆分。接下来,我检查父元素是否也必须被拆分。如果是,我会克隆并清空它们,将原始元素的第二部分移动到克隆体中,并将它们插入到原始元素之后,如下所示:
var tail = textNode.splitText( offset );
var $parent = $(textNode).parent();

if ($parent.is("span")) {
    var $tail = $parent.clone();
    $tail.contents().remove();
    $tail = $tail.append(tail).insertAfter($parent);

    if ($parent.parent().is("a")) {
        $tail = $parent.parent().clone();
        $tail.contents().remove();
        $tail = $tail.append($tail).insertAfter($parent.parent());
    }

    return $tail[0];
}
else if ($parent.is("a")) {
    var $tail = $parent.clone();
    $tail.contents().remove();
    $tail = $tail.append(tail).insertAfter($parent);

    return $tail[0];
}
return tail;

问题在于,tail只包含TextNode的第二部分。接下来的<span />没有移动,所以HTML被搞乱了,如下所示(选择过程中丢失,但不重要):
Lor em <a>ips <span>dolor</span></a> <a>um</a>

我也尝试过$(tail).nextAll(),但它似乎返回一个空集合。有人有想法如何实现这个吗?如果有任何不清楚的地方,请询问更多细节。
编辑:像建议的那样,我创建了以下链接http://jsfiddle.net/7PdLd/4/

你能否提供一个jsfiddle链接以便更加清晰地展示它? - Genzotto
4
好的,我已经翻译了:@Genzotto 好主意,我照做了:http://jsfiddle.net/7PdLd/4/。 - hielsnoppe
1个回答

4
这似乎是可行的:

演示

function start () {
    var range = window.getSelection().getRangeAt(0);
    split(
        range.startContainer,
        range.startOffset,
        range.commonAncestorContainer,
        false
    );
    split(
        range.endContainer,
        range.endOffset,
        range.commonAncestorContainer,
        true
    );  
}
function split(node, offset, ancestor, backwards) {
    var clone;
    if(backwards) {
        clone = node;
        node = node.splitText(offset);
    }else{
        clone = node.splitText(offset);
    }
    if(node == ancestor) return;
    var parent;
    while((parent = node.parentNode) && parent != ancestor) {
        var parentClone = parent.cloneNode(false);
        appendUntil(parentClone, parent, node, !backwards);
        parentClone.insertBefore(clone, backwards ? null : parentClone.firstChild);
        node = parent;
        clone = parentClone;
    }
    insertAdjacent(ancestor, clone, node, backwards);
}
function appendUntil(target, parent, until, fromEnd) {
    var from, to, sibling;
    if(fromEnd) {
        from = until.nextSibling;
        to = null;
    } else {
        from = parent.firstChild;
        to = until;
    }
    while(from && from != to) {
        sibling = from.nextSibling;
        target.appendChild(from);
        from = sibling;
    }
}
function insertAdjacent(parent, newEl, refEl, before) {
    parent.insertBefore(newEl, before ? refEl : refEl.nextSibling);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接