zoukankan      html  css  js  c++  java
  • Javascript标准DOM Range操作

    简介

    Range是一种fragment(HTML片断),它包含了节点或文本节点的一部分。 可以通过document.createRange()或selection象的getRangeAt()方法获得。

    createRange()是在2级DOM里定义的一个方法,它属于document对象。IE是不支持此方法的,因此需要检测浏览器的支持性。

    if (document.implementation && document.implementation.hasFeature && document.implementation.hasFeature("Range", "2.0")) {
        var oRange = document.createRange();    // 支持
    } else {
        // 不支持
    }

    属性

    当创建一个Range对象后,该对象就有了以下属性,以下属性全为“只读”。

    startContainer
    包含“起点”的节点。“包含”的意思是起点所属的节点。
    endContainer
    包含“结束点”的节点
    startOffset
    “起点”在startContainer中的偏移量。
    如果startContainer是文本节点、注释节点或CDATA节点,则返回“起点”在startContainer中字符偏移量。
    如果startContainer是元素节点,则返回“起点”在startContainer.childNodes中的次序。
    <p id="p1"><span>span</span><b id="b1">Hello</b> World</p>
    <script type="text/javascript">
        var oP1 = document.getElementById('p1')
        var oB1 = document.getElementById('b1');
        var oRange = document.createRange();
        oRange.setStart(oB1.firstChild, 2); // 设置range的“起点”
        oRange.setEnd(oP1.lastChild, 3);    // 设置range的“结束点”
        alert(oRange.startOffset);          //  2,可看到“起点”在<b id="b1">Hello</b>应是第三个字符。
        alert(oRange.startContainer);       // 元素oB1.firstChild,文本节点
    </script>
    <p id="p1"><span>span</span><b id="b1">Hello</b> World</p>
    <script type="text/javascript">
        var oP1 = document.getElementById('p1')
        var oB1 = document.getElementById('b1');
        var oRange = document.createRange();
        oRange.setStartBefore(oB1);       // 设置range的“起点”
        oRange.setEnd(oP1.lastChild, 3);  // 设置range的“结束点”
        alert(oRange.startOffset);        // 1,可以看到“起点”应是oP1的第2个子节点
        alert(oRange.startContainer);     // 元素oP1
    </script>
    endOffset
    “起点”在endContainer中的偏移量,其它细节同startOffset。
    commonAncestorContainer
    第一个包含Range的节点,同时包含起点和结束点。
    collapsed
    起点和结束点在一起时为true;Range对象为空(刚createRange()时)也为true。

    定位(设置“起点”和“结束点”)的一些方法

    setStart(node, offset)和setEnd(node, offset)
    setStart:设置起点的位置,node是对startContainer的引用,偏移则是startOffset;
    setEnd:设置结束点的位置,node是对endContainer的引用,偏移则是startOffset;
    <p id="p1"><b>Hello</b> World</p>
    <script>
        var oP1 =  document.getElementById("p1");
        var oHello = oP1.firstChild.firstChild;
        var oWorld = oP1.lastChild;
        var oRange = document.createRange();
        oRange.setStart(oHello, 2);
        oRange.setEnd(oWorld, 3);
    </script>
    此时选中的fragment不是well-formed,浏览器会自动添加一些元素,最终形成下面的fragment。
    <p  id="p1"><b>He</b><b>llo</b> World</p>
    注意well-formed这一步骤是隐藏的,也就是说利用CSS中“b + b {}”是选不到第二个b元素的。
    setStartBefore(referenceNode)、setStartAfter(referenceNode)
    setEndBefore(referenceNode)、setEndAfter(referenceNode)
    setStartBefore:将“起点”设置到referenceNode前
    setStartAfter:将“起点”设置到referenceNode后
    setEndBefore:将“结束点”设置到referenceNode前
    setEndAfter:将“结束点”设置到referenceNode后
    注意:使用这四个方法设置的“起点”或“结束点”的父节点与referenceNode的父节点是同一个元素。
    selectNode(referenceNode)和selectNodeContents(referenceNode)
    selectNode:设置Range的范围,包括referenceNode和它的所有后代(子孙)节点。
    selectNodeContents:设置Range的范围,包括它的所有后代节点。
    二者的区别:

    collapse(toStart)
    折叠该范围,使它的“起点”和“结束点”重合。
    参数toStart,true时折叠到Range边界的首部,为false时折叠到Range尾部,默认为false。

    修改范围的方法

    cloneContents()
    可以克隆选中Range的fragment并返回改fragment。这个方法类似于extractContents(),但是不是删除,而是克隆。
    deleteContents()
    从Dom中删除Range选中的fragment。注意该函数没有返回值(实际上为undefined)。
    extractContents()
    将选中的Range从DOM树中移到一个fragment中,并返回此fragment。
    <p id="p1"><b>Hello</b> World</p>
    <script>
        var oP1 =  document.getElementById("p1");
        var oHello = oP1.firstChild.firstChild;
        var oWorld = oP1.lastChild;
        var oRange = document.createRange();
        oRange.setStart(oHello, 2);
        oRange.setEnd(oWorld, 3);
        var oFragment = oRange.extractContents();
        document.body.appendChild(oFragment);
        // 不可以使用document.body.appendChild(oRange); 因为oRange是range对象。
    </script>
    运行后HTML结构,体现了前面提到的well-formed原则。
    <body>
      <p id="p1"><b>He</b>rld</p>
      <b>llo</b> Wo
    </body>
    insertNode
    方法可以插入一个节点到Range中,注意会插入到Range的“起点”。
    <p id="p1"><b>Hello</b> World</p>
    <script>
        var oP1 = document.getElementById("p1");
        var oHello = oP1.firstChild.firstChild;
        var oWorld = oP1.lastChild;
        var oRange = document.createRange();
        var oSpan = document.createElement("span");
        oSpan.appendChild(document.createTextNode("Inserted text"));
     
        oRange.setStart(oHello, 2);
        oRange.setEnd(oWorld, 3);
        oRange.insertNode(oSpan);
    </script>
    运行后HTML结构:
    <body>    
        <p id="p1"><b>He<span>Inserted text</span>llo</b> World</p>
    </body>
    surroundContents()
    <p id="p1"><b>Hello</b> World</p>
    <script>
        var oP1 = document.getElementById("p1");
        var oHello = oP1.firstChild.firstChild;
        var oWorld = oP1.lastChild;
        var oRange = document.createRange();
        var oSpan = document.createElement("span");
        oRange.setStart(oHello, 2);
        oRange.setEnd(oWorld, 3);
        oRange.surroundContents(oSpan);
    </script>
    因为部分地选择了“<b>oHello</b>”,所以会抛出“BAD_BOUNDARYPOINTS_ERR”错误(虽然会自动添加“<b>”让元素“well-formed”,仍然会报错)。下面的代码将能够正常运行:
    <p id="p1"><b>Hello</b> World</p>
    <script>
        var oP1 = document.getElementById("p1")
        var oRange = document.createRange();
        var oSpan = document.createElement("span");
        oRange.setStart(oP1, 0);
        oRange.setEnd(oP1.lastChild, 3);
        oRange.surroundContents(oSpan);
    </script>
    运行后,HTML将变成
    <p id="p1"><span><b>Hello</b>  Wo</span>rld</p>

    其它的方法

    cloneRange()
    var oNewRange = oRange.cloneRange();
    cloneRange()方法将返回一个当前Range的副本,它也是Range对象。
    注意它和cloneContents()的区别在于返回值不同,一个是HTML片段,一个是Range对象
    compareBoundaryPoints()
    var compare = comparerange.compareBoundaryPoints(how, sourceRange);
    compare:返回1, 0, -1.(0为相等,1为时,comparerange在sourceRange之后,-1为comparerange在sourceRange之前)。
    how:比较哪些边界点,为常数。
    • Range.START_TO_START - 比较两个 Range 节点的开始点
    • Range.END_TO_END - 比较两个 Range 节点的结束点
    • Range.START_TO_END - 用 sourceRange 的开始点与当前范围的结束点比较
    • Range.END_TO_START - 用 sourceRange 的结束点与当前范围的开始点比较
    sourceRange:个Range对象的边界。
    detach()
    虽然GC(垃圾收集器)会将其收集,但用detach()释放range对象是一个好习惯。语法为:oRange.detach();
    toString()
    返回该范围表示的文档区域的纯文本内容,不包含任何标签。

    参考链接

  • 相关阅读:
    源码解析.Net中IConfiguration配置的实现
    python小工具
    hue搭建以及报错记录
    jenkins启动指定数据目录
    基于三维地图的智慧园区可视化解决方案
    工业4.0的下一个十年
    项目管理知识体系介绍
    人工智能发展的新方向
    速成财务产品经理
    标准化体系:运营—训练—督导
  • 原文地址:https://www.cnblogs.com/rainman/p/1967488.html
Copyright © 2011-2022 走看看