使用javascript扩展DOM范围以覆盖部分选定的节点

时间:2010-03-19 12:29:16

标签: javascript dom

我正在开发一个像Web应用程序这样的富文本编辑器,基本上是用javascript编写的XML编辑器。

我的javascript代码需要从contentEditable div容器中包装一系列节点。 我正在使用MDC中描述的方法。但由于我需要将div容器内容同步到我的XML DOM,我想避免部分选择,如w3c ranges中所述:

<BODY><H1>Title</H1><P>Blah xyz.</P></BODY

............^----------------^............

此选择在H1内部开始并在P内结束,我希望它完全包含H1,P。

是否有一种简单的方法可以扩展选择以完全覆盖部分选定的孩子? 基本上我想使用range.surroundContents()而不会遇到异常。

(代码不需要使用opera / IE)

3 个答案:

答案 0 :(得分:9)

查看MDC文档,我管理了类似的事情:

Selection.prototype.coverAll = function() {
    var ranges = [];
    for(var i=0; i<this.rangeCount; i++) {
        var range = this.getRangeAt(i);
        while(range.startContainer.nodeType == 3
              || range.startContainer.childNodes.length == 1)
            range.setStartBefore(range.startContainer);
        while(range.endContainer.nodeType == 3
              || range.endContainer.childNodes.length == 1)
            range.setEndAfter(range.endContainer);
        ranges.push(range);
    }
    this.removeAllRanges();
    for(var i=0; i<ranges.length; i++) {
        this.addRange(ranges[i]);
    }
    return;
};

您可以在此处试用:http://jsfiddle.net/GFuX6/9/

编辑: 更新以使浏览器正确显示增强选择。即使选择包含多个范围(使用Ctrl),它也能满足您的要求。

要使多个部分节点粗体化,这是一个解决方案:

Selection.prototype.boldinize = function() {
    this.coverAll();
    for(var i=0; i<this.rangeCount; i++) {
        var range = this.getRangeAt(i);
        var parent = range.commonAncestorContainer;
        var b = document.createElement('b');
        if(parent.nodeType == 3) {
            range.surroundContents(b);
        } else {
            var content = range.extractContents();
            b.appendChild(content);
            range.insertNode(b);
        }
    }
};

答案 1 :(得分:0)

如果您的意思是要包含标签H1和P(即有效标记),请不要担心。你可以免费获得。如果您的意思是要包含(部分)选择中的所有内容,则需要访问Selection对象。在Quirksmode's introduction to Range上阅读相关内容。

答案 2 :(得分:0)

感谢Alsciende,我终于在http://jsfiddle.net/wesUV/21/找到了代码。 这种方法并不像另一种方法那样贪婪。在coverAll()之后,surroundContents()应该始终有效。

Selection.prototype.coverAll = function() {
  var ranges = [];   
  for(var i=0; i<this.rangeCount; i++) {
    var range = this.getRangeAt(i);
    var ancestor = range.commonAncestorContainer;
    if (ancestor.nodeType == 1) {            
        if (range.startContainer.parentNode != ancestor && this.containsNode(range.startContainer.parentNode, true)) {
            range.setStartBefore(range.startContainer.parentNode);
        }
        if (range.endContainer.parentNode != ancestor && this.containsNode(range.endContainer.parentNode, true)) {
                range.setEndAfter(range.endContainer.parentNode);
        }
    }
    ranges.push(range);
  }
  this.removeAllRanges();
  for(var i=0; i<ranges.length; i++) {
    this.addRange(ranges[i]);
  }
  return;
};

大胆的功能:

Selection.prototype.boldinize = function() {
  for(var i=0; i<this.rangeCount; i++) {        
    var range = this.getRangeAt(i);
    var b = document.createElement('b');
    try {
        range.surroundContents(b);
    } catch (e) {
        alert(e);
    }
  }
};