html5之Range对象详解

作者: 便U_Life | 来源:发表于2016-07-06 16:59 被阅读3173次

    一:Range对象的概念

    Range对象代表页面上一段连续的区域,通过Range对象可以获取或者修改页面上任何区域的内容。也可以通过Range的方法进行复制和移动页面任何区域的元素。
    在Js的document文档中有一个方法用来创建一个Range对象,代码如下:

    var  range = document.createRange();
    

    在html5中,每一个浏览器窗口都会有一个selection对象,代表用户鼠标在页面中所选取的区域,(注意:经过测试IE9以下的浏览器不支持Selection对象), 可以通过如下语句创建selection对象;

    var  selection = document.getSelection();   
    或者
    var  selection  = window.getSelection();
    

    每一个selection对象都有一个或者多个Range对象,每一个range对象代表用户鼠标所选取范围内的一段连续区域,在firefox中,可以通过ctrl键可以选取多个连续的区域,因此在firefox中一个selection对象有多个range对象,在其他浏览器中,用户只能选取一段连续的区域,因此只有一个range对象。
    可以通过selection对象的getRangeAt方法来获取selection对象的某个Range对象,如下:
    getRangeAt方法有一个参数index,代表该Range对象的序列号;我们可以通过Selection对象的rangeCount参数的值判断用户是否选取了内容;
    1.当用户没有按下鼠标时候,该参数的值为0.
    2.当用户按下鼠标的时候,该参数值为1.
    3.当用户使用鼠标同时按住ctrl键时选取了一个或者多个区域时候,该参数值代表用户选取区域的数量。
    4.当用户取消区域的选取时,该属性值为1,代表页面上存在一个空的Range对象;
    测试代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>meter</title>
    </head>
    <body>
        <script>
           function rangeTest() {
                var  html,
                showRangeDiv = document.getElementById("showRange"),
                 selection = document.getSelection();
                if(selection.rangeCount > 0) {
                    html = "你选取了" + selection.rangeCount + "段内容<br/>";
                    for(var i = 0; i < selection.rangeCount; i++) {
                        var range = selection.getRangeAt(i);
                        html += "第" + (i + 1) + "段内容为:" + range + "<br/>";
                    }
                    showRangeDiv.innerHTML = html;
                }
            }
        </script>
        <h3>selection对象与range对象的使用实例</h3>
        <input type="button" value="点击我" onclick="rangeTest()"/>
        <div id="showRange"></div>
    </body>
    </html>
    

    效果:


    range_selection.png

    二:Range对象的属性和方法

    (1)属性

    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>
    

    collapsed:
    起点和结束点在一起时为true;Range对象为空(刚createRange()时)也为true。
    commonAncestorContainer
    第一个包含Range的节点,同时包含起点和结束点。

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

    setStart(node, offset)和setEnd(node, offset)
    setStart:设置起点的位置,node是对startContainer的引用,偏移则是startOffset;
    setEnd:设置结束点的位置,node是对endContainer的引用,偏移则是startOffset;
    代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
     <meta charset="UTF-8">
     <title>range3</title>
     <script>
      function deleteChar() {
          var div = document.getElementById("myDiv");
          var textNode = div.firstChild;
          var rangeObj = document.createRange();
          rangeObj.setStart(textNode,1);
         rangeObj.setEnd(textNode,4);
         rangeObj.deleteContents();
    }
    </script>
    </head>
    <body>
         <div id="myDiv" style="color:red">这段文字是用来删除的</div>
         <button onclick="deleteChar()">删除文字</button>
    </body>
    </html>
    

    setStartBefore(referenceNode)、setStartAfter(referenceNode)
    setEndBefore(referenceNode)、setEndAfter(referenceNode)

    setStartBefore:将“起点”设置到referenceNode前
    setStartAfter:将“起点”设置到referenceNode后
    setEndBefore:将“结束点”设置到referenceNode前
    setEndAfter:将“结束点”设置到referenceNode后
    注意:使用这四个方法设置的“起点”或“结束点”的父节点与referenceNode的父节点是同一个元素。
    代码如下:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
            <script type="application/javascript">
                function delrow(){
                    var table=document.getElementById("mytable");
                    if(table.rows.length>0){
                        var row=table.rows[0];
                        var rangeObj=document.createRange();
                        rangeObj.setStartBefore(row);
                        rangeObj.setEndAfter(row);
                        rangeObj.deleteContents();
                    }
                }
            </script>
        </head>
        <body>
            <table id="mytable" border="1">
                <tr>
                    <td>内容1</td>
                    <td>内容2</td>
                </tr>
                <tr>
                    <td>内容3</td>
                    <td>内容4</td>
                </tr>
            </table>
            <button onclick="delrow()">删除第一行</button>
        </body>
    </html>
    

    selectNode(referenceNode)和selectNodeContents(referenceNode)
    selectNode:设置Range的范围,包括referenceNode和它的所有后代(子孙)节点。
    selectNodeContents:设置Range的范围,包括它的所有后代节点。
    二者的区别:

    range_selection.png

    (3)修改范围的方法

    cloneRange()
    cloneRange()方法将返回一个当前Range的副本,它也是Range对象。
    注意它和cloneContents()的区别在于返回值不同,一个是HTML片段,一个是Range对象 。代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>meter</title>
    </head>
    <body>
        <p id="p">这里是随便书写的内容</p>
        <button onclick="cloneRange()">克隆</button>
    </body>
    <script>
        function cloneRange() {
        var rangeObj = document.createRange();
        rangeObj.selectNodeContents(document.getElementById("p"));
        var rangeClone = rangeObj.cloneRange();
        alert(rangeClone.toString());
        }
    </script>
    </html>
    

    cloneContents()
    可以克隆选中Range的fragment并返回改fragment。这个方法类似extractContents(),但不是删除,而是克隆。代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>meter</title>
    </head>
    <body>
         <p id="p">这里是随便书写的内容</p>
         <button onclick="cloneContents()">克隆</button>
    </body>
        <script>
             function cloneContents() {
                 var rangeObj = document.createRange();
                 rangeObj.selectNodeContents(document.getElementById("p"));
                 var rangeClone = rangeObj.cloneContents();
                 alert(rangeClone.toString());
             }
        </script>
    </html>
    

    deleteContents()
    从Dom中删除Range选中的fragment。注意该函数没有返回值(实际上为undefined)。
    代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>meter</title>
    </head>
    <body>
         <p id="p">这里是随便书写的内容</p>
         <button onclick="delRange()">删除</button>
    </body>
        <script>
             function delRange() {
                 var rangeObj = document.createRange();
                 rangeObj.selectNodeContents(document.getElementById("p"));
                 var rangeClone = rangeObj.deleteContents();             
             }
        </script>
    </html>
    

    extractContents()
    将选中的Range从DOM树中移到一个fragment中,并返回此fragment。代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>meter</title>
    </head>
    <body>
        <div id="srcDiv" style="background-color:aquamarine;width:300px;height:50px;">你好吗?</div>
        <div id="distDiv" style="background-color:bisque;width:300px;height:50px"></div>
        <button onclick="moveContent()">移动元素</button>
    </body>
    <script>
        function moveContent() {
            var srcDiv = document.getElementById("srcDiv");
            var distDiv = document.getElementById("distDiv");
            var rangeObj = document.createRange();
            rangeObj.selectNodeContents(srcDiv);
            var docFrangMent = rangeObj.extractContents();
            distDiv.appendChild(docFrangMent);
        }
    </script>
    </html>
    

    insertNode
    insertNode方法可以插入一个节点到Range中,注意会插入到Range的“起点”。代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>meter</title>
    </head>
    <body>
        <p id="p1"><b>Hello</b> World</p>
    </body>
    <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>
    

    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()
    返回该范围表示的文档区域的纯文本内容,不包含任何标签;

    谢谢观看,希望对您有帮助。一起学前端一起成长!(__) 嘻嘻……

    相关文章

      网友评论

      • ohasdo:带例子的都是好学生。
      • zhouatie:能加个好友吗 有问题想问你
      • 白衣书生1109:HTML初学者,小白一个,望多多指教
        大狗奇:不错,很详细。最近正好有对range操作的需求
        白衣书生1109:@便U_Life :grin:
        便U_Life:@深蓝浅白 其实我也差不多,我也在巩固。后面还有很多要学的,一起努力吧

      本文标题:html5之Range对象详解

      本文链接:https://www.haomeiwen.com/subject/vaekjttx.html