1.理解Range对象

   重新来学习下HTML5中的Range对象和Selection对象,最近在维护富文本编辑器,感觉这方面的知识点很有用,所以趁着周末多学习下~ 

什么是Range对象?
在HTML5中,一个Range对象代表页面上的一段连续区域。可以通过如下语句创建一个空的Range对象。如下代码:

var range = document.createRange();

什么是Selection对象?
在HTML5中,每一个浏览器窗口都有一个Selection对象,代表用户鼠标在页面中所选取的区域。可以通过如下代码得到一个Selection对象:

var selection = window.getSelection();

var selection = document.getSelection();

Selection对象与Range对象的区别是?
每一个Selection对象都有一个或多个Range对象,每一个Range对象代表用户用鼠标所选取范围内的一段连续区域。

Firefox 与 chrome,safari对Selection的区别?
   在Firefox浏览器中,用户可以通过按住 ctrl键来选取页面上的多个区域,因此一个Selection对象可能有多个Range对象。
   在chrome或safari浏览器中,用户每次只能选取一段区域,所以一个Selection对象中只能有一个Range对象。

如何获取Selection对象中的某个Range对象呢?
可以通过Selection对象的getRangeAt方法来获取。代码如下:

var range = document.getSelection().getRangeAt(rangeIndex);

rangeIndex 代表Range对象的序号,在chrome或safari中,用户每次只能选取一段区域,因此该值只能为0;

如何判断用户是否选取了内容?
可以通过Selection对象的 rangeCount 属性来判断;
  1. 用户没有按下鼠标该属性值为0;
  2. 用户按下鼠标之后该属性值为1;
  3. 用户用鼠标加ctrl键选取了一个或多个区域时,该属性值代表用户通过鼠标选取的区域的数量,当用户取消该区域的选取之后,该属性值为1.
下面是一个demo;页面上显示一段文字和一个按钮,当用户单击按钮时弹出的提示框中显示用户用鼠标加ctrl键共选取了多少个区域及每一段区域中的内容。代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<title>标题</title>
</head>
<body>
<h3>Selection对象与Range对象使用demo</h3>
<input type="button" value="选中我然后点击" onClick="rangeTest()" />
<div id="showRange"></div>
<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>
</body>
</html>

查看效果

1-2 Range对象的属性有哪些?
我们在页面上创建的代码如下:

var rangeObj = document.createRange();
console.log(rangeObj);

打印后看到有如下属性:
collapsed: (Boolean) 用于判断Range对象所代表的区域的开始点和结束点是否位于相同的位置,如果相同该属性值为true。
commonAncestorContainer: (node) 返回Range对象所代表的区域位于什么节点之中。
endContainer: (node) 用于返回Range对象所代表的区域的终点位于什么节点之中。
endOffset(int) 用于返回Range对象所代表区域的终点与包含该终点的节点起点之间的距离。
startContainer: (node) 用于返回Range对象所代表区域的起点位于什么节点之中。
startOffset (int) 用于返回Range对象所代表的区域的起点与包含该起点节点的起点之间的距离。

2 Range对象的方法
   2-1 理解使用 selectNode, selectNodeContents, 与 deleteContents方法
selectNode: Range对象的selectNode 方法用于将Range对象的起点指定为某个节点的起点,将Range对象的终点指定为该节点的终点。Range对象所代表的区域包含该节点。
使用方法如下:
rangeObj.selectNode(node);
demo举例理解
假如页面上有一个div,该div包含内容,如果使用 rangeObj.selectNode("div"); 的含义是,选择该div内的所有内容,包括该div标签本身。

selectNodeContents: 该方法用于将Range对象的起点指定为某个节点中的所有内容的起点,将Range对象的终点指定为该节点所有内容的终点,也就是说使Range对象所代表的区域包含该节点的所有内容,但是不包括该节点标签本身。

使用方法如下:
rangeObj.selectNodeContents(node);
demo举例理解:
还是上面的div元素,该元素包含内容,如果使用 rangeObj.selectNodeContents('div');的话,的含义是,选择该div内的所有内容,但是不包括该div本身。

deleteContents: 该方法用于将Range对象中所包含的内容从页面中删除。
使用方法如下:
rangeObj.deleteContents();

下面是使用一个demo来理解上面的三个方法的具体含义,页面中有一个div元素,一个删除内容的按钮,和一个删除元素的按钮,div元素中显示一些文字,当用户单击 "删除内容"按钮时,会将div元素中的文字从页面中删除,单击 “删除元素” 按钮时,会将整个div元素从页面中删除。

代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<title>标题</title>
</head>
<body>
<h3>Selection对象与Range对象使用demo</h3>
<div id="div" style="background-color: #e0a0b0; width:300px; height: 50px;">aaaaadsadsdasadsbbgg</div>
<button onclick="deleteRangeContents(true);">删除内容</button>
<button onclick="deleteRangeContents(false);">删除元素</button> <script>
function deleteRangeContents(flag) {
var div = document.getElementById("div");
var rangeObj = document.createRange();
if (flag) {
rangeObj.selectNodeContents(div);
} else {
rangeObj.selectNode(div);
}
rangeObj.deleteContents();
}
</script>
</body>
</html>

查看效果

2-2 理解使用 setStart方法,setEnd方法,setStartBefore方法,setStartAfter方法,setEndBefore方法与setEndAfter方法

setStart: 该方法用于将某个节点中的某个位置指定为Range对象所代表区域的起点位置。使用方法如下:
  rangeObj.setStart(node, num);
  num的含义是:首先它是一个整型数值,有两种含义取决于node节点;
    1. 当第一个参数node所代表的节点是一个内容为一段文字的时候,那么该参数值用于指定将第几个文字结束位置作为Range对象所代表区域的起点位置(num是从0开始)
    2. 当第一个参数node所代表的节点包括其他子节点时,该参数用于指定将第几个子节点的结束位置作为Range对象所代表区域的起点位置。

setEnd: 该方法用于将某个节点中的某处位置指定为Range对象所代表区域的结束位置。使用方法如下:
   rangeObj.setEnd(node, num);
   num的含义: 首先是一个整型数值;
     1. 当第一个参数node所代表的节点是一个内容为一段文字的时候,该参数指定将第几个文字结束位置作为Range对象所代表区域的结束位置。
     2. 当第一个参数node所代表的节点包括其他子节点时,该参数值用于指定将第几个子节点的结束位置作为Range对象所代表区域的结束位置。

下面是一个简单的demo来理解上面的 setStart和setEnd方法的使用,页面上有一个div元素和一个删除文字的按钮,div元素中有一些文字,当用户点击 删除文字按钮时,div元素中的第三个文字到第十个文字将被删除。
代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<title>标题</title>
</head>
<body>
<div id="myDiv" style="color: red">这段文字中第三个文字到第十个文字将被删除</div>
<button onclick="deleteChar()">删除文字</button>
<script>
function deleteChar() {
var div = document.getElementById("myDiv");
var textNode = div.firstChild;
var rangeObj = document.createRange();
rangeObj.setStart(textNode, 2);
rangeObj.setEnd(textNode, 10);
rangeObj.deleteContents();
}
</script>
</body>
</html>

查看效果

setStartBefore: 该方法用于将某个节点的起始位置指定为Range对象所代表区域的起点位置。使用方法如下:
rangeObj.setStartBefore(node);

setStartAfter: 该方法用于将某个节点的终点位置指定为Range对象所代表区域的起点位置。使用方法如下:
rangeObj.setStartAfter(node);

setEndBefore: 该方法用于将某个节点的起始位置指定为Range对象所代表区域的终点位置,使用方法如下:
rangeObj.setEndBefore(node);

setEndAfter: 该方法用于将某个节点的终点位置指定为Range对象所代表区域的终点位置。使用方法如下:
rangeObj.setEndAfter(node);

看上面的四个方法容易混淆,我们来做一个demo,使用一下 setStartBefore 和 setEndAfter方法。 页面上有一个表格和一个按钮,用户单击按钮时,通过Range对象的setStartBefore 和 setEndAfter方法 使Range对象代表的区域包含表格的第一行,然后删除该行。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<title>标题</title>
</head>
<body>
<table id="myTable" border="1" cellspacing="0" cellpadding="0">
<tr>
<td>第一行第一列</td>
<td>第一行第二列</td>
</tr>
<tr>
<td>第二行第一列</td>
<td>第二行第二列</td>
</tr>
</table>
<button onclick="deleteFirstRow()">删除第一行</button>
<script>
function deleteFirstRow() {
var myTable = document.getElementById('myTable');
if (myTable.rows.length > 0) {
var row = myTable.rows[0];
var rangeObj = document.createRange();
rangeObj.setStartBefore(row);
rangeObj.setEndAfter(row);
rangeObj.deleteContents();
}
}
</script>
</body>
</html>

查看效果

2-3 理解使用 cloneRange方法,cloneContents方法,extractContents方法

cloneRange: 该方法用于对当前的Range对象进行复制,该方法返回复制的Range对象。使用方法如下:
   var rangeClone = rangeObj.cloneRange();
下面可以看一个demo来理解一下,页面上显示一个 "克隆Range对象" 按钮,用户单击该按钮时,创建一个Range对象,该对象包含页面中的所有内容,然后使用cloneRange方法复制Range对象,然后在弹窗显示该Range对象中的内容。
代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<title>标题</title>
</head>
<body>
<button onclick="cloneRange()">克隆Range对象</button>
<script>
function cloneRange() {
var rangeObj = document.createRange();
rangeObj.selectNodeContents(document.body);
var rangeClone = rangeObj.cloneRange();
console.log(rangeClone);
alert(rangeClone.toString());
}
</script>
</body>
</html>

查看效果

cloneContents: 该方法用于在页面上追加一段HTML代码,使用方法如下:
var docFragment = rangeObj.cloneContents();
该方法返回的是 一个 DocumentFragment对象,该对象为一个容器元素,当需要追加,修改,删除或查找页面上的元素时,该方法非常有用。
下面是一个demo,页面上显示一个div元素,div元素中包含一些文字和一个按钮,用户点击按钮时将在该div元素底部克隆出相同的文字和按钮。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<title>标题</title>
</head>
<body>
<div id="div">
<span>aaaaaa</span>
<button onclick="cloneDivContent()">克隆</button>
</div>
<script>
function cloneDivContent() {
var div = document.getElementById('div');
var rangeObj = document.createRange();
rangeObj.selectNodeContents(div);
var documentFragment = rangeObj.cloneContents();
div.appendChild(documentFragment);
}
</script>
</body>
</html>

查看效果

extraContents: 该方法用于将Range对象所代表区域的HTML代码克隆到一个 DocumentFragment中,然后从页面中删除这段HTML代码;

使用方法如下:
var documentFragment = rangeObj.extraContents();

下面是一个demo, 页面上有2个div元素和一个按钮,其中第一个div元素包含一些文字,用户单击该按钮时,把文字移动到第二个div中。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<title>标题</title>
</head>
<body>
<div id="srcDiv" style="background-color: red; width: 300px; height:50px">adsddasdssdsdsdsads</div>
<div id="distDiv" style="background-color: blue; width: 300px; height: 50px;"></div>
<button onclick="moveContent()">移动元素内容</button> <script>
function moveContent() {
var srcDiv = document.getElementById('srcDiv');
var distDiv = document.getElementById("distDiv");
var rangeObj = document.createRange();
rangeObj.selectNodeContents(srcDiv);
var documentFragment = rangeObj.extractContents();
distDiv.appendChild(documentFragment);
}
</script>
</body>
</html>

查看效果

2-4 insertNode方法
该方法用于将指定的节点插入到某个Range对象所代表的区域中,插入位置为Range对象所代表区域的起点位置,如果该节点已经存在于页面之中,那么该节点
将被移动到Range对象所代表区域的起点处。
使用方法如下:
rangeObj.insertNode(node)

下面是一个demo,页面中有一个div元素和一个按钮,div元素有一些文字,在div元素中按下鼠标左键时,该按钮将被移动到按下鼠标左键的位置。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<title>标题</title>
</head>
<body>
<div onmouseup="moveButton()" style="width: 400px; background-color: red;">adssdasddsdasszczxccxzcx</div>
<button id="button">按钮</button> <script>
function moveButton() {
var button = document.getElementById("button");
var selection = document.getSelection();
if (selection.rangeCount > 0) {
var range = selection.getRangeAt(0);
range.insertNode(button);
}
}
</script>
</body>
</html>

查看效果

2-5 理解collapse方法 和 detach方法
该方法用于将Range对象所代表的区域的终点移动到该区域的起点处,或将Range对象所代表的区域的起点移动到终点处,使Range对象所代表的区域内不包含任何内容。
使用方法如下:
RangeObj.collapse(toStart);
参数toStart,是一个Boolean型,如果为false的话,表示将Range对象所代表的区域的起点移动到终点处,当为true的话,表示将Range对象所代表的区域的终点移动到该区域的起点处。
下面是一个demo,可以来理解下 collapse方法的使用;
页面上有一个div元素,里面包含一些文字,一个 选择元素的 按钮,一个 取消选择元素的按钮,和一个 显示Range内容的按钮,用户单击 选择元素 按钮时该Range对象中将包含页面中的div元素,然后单击 显示Range内容按钮 就弹出 该div元素的内容,再单击 取消选择按钮 将使用Range对象的collapse方法清空Range对象的内容。再次单击 显示Range内容,将显示空字符串。
代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<title>标题</title>
</head>
<body>
<div id="div" style="background-color: red; width:300px; height: 50px;">元素中的内容</div>
<button onclick="selectRangeContents()">选择元素</button>
<button onclick="unselect()">取消选择</button>
<button onclick="showRange()">显示Range内容</button>
<script>
var rangeObj = document.createRange();
function selectRangeContents() {
var div = document.getElementById('div');
rangeObj.selectNode(div);
}
function unselect() {
rangeObj.collapse(false);
}
function showRange() {
alert(rangeObj.toString());
}
</script>
</body>
</html>

查看效果

detach方法: 该方法用于从浏览器中释放Range对象,释放之后将不能再访问该Range对象,否则将抛出脚本错误,使用方法如下:
RangeObj.detach();

理解HTML5中Range对象的更多相关文章

  1. VB类模块中属性的参数——VBA中Range对象的Value属性和Value2属性的一点区别

    在VB中,属性是可以有参数的,而VBA中属性使用参数非常常见.比如最常用的:Worksheet.Range("A1:A10")  VB的语法,使用参数的不一定是方法,也有可能是属性 ...

  2. 深入理解JS中的对象(二):new 的工作原理

    目录 序言 不同返回值的构造函数 深入 new 调用函数原理 总结 参考 1.序言 在 深入理解JS中的对象(一):原型.原型链和构造函数 中,我们分析了JS中是否一切皆对象以及对象的原型.原型链和构 ...

  3. 深入理解JS中的对象(三):class 的工作原理

    目录 序言 class 是一个特殊的函数 class 的工作原理 class 继承的原型链关系 参考 1.序言 ECMAScript 2015(ES6) 中引入的 JavaScript 类实质上是 J ...

  4. 【学习笔记】六:面向对象的程序设计——理解JS中的对象属性、创建对象、JS中的继承

    ES中没有类的概念,这也使其对象和其他语言中的对象有所不同,ES中定义对象为:“无序属性的集合,其属性包含基本值.对象或者函数”.现在常用的创建单个对象的方法为对象字面量形式.在常见多个对象时,使用工 ...

  5. 理解Java中的对象,变量和方法

    1.对象的创建和销毁 1.1 对象的创建 这里只介绍创建对象与构造方法的关系 (1).每实例化一个对象就会自动调用一次构造方法,实质上这个过程就是创建对象的过程,准确的说,在Java语言中使用new操 ...

  6. 深入理解JS中的对象(一)

    目录 一切皆是对象吗? 对象 原型与原型链 构造函数 参考 1.一切皆是对象吗? 首先,"在 JavaScript 中,一切皆是对象"这种表述是不完全正确的. JavaScript ...

  7. WPF教程九:理解WPF中的对象资源

    在WPF中,所有继承自FrameworkElement的元素都包含一个Resources属性,这个属性就是我们这篇要讲的资源. 这一篇讲解的资源是不是上一篇的程序集资源(那个是在编译过程中打包到程序集 ...

  8. 全面理解Javascript中Function对象的属性和方法

    http://www.cnblogs.com/liontone/p/3970420.html 函数是 JavaScript 中的基本数据类型,在函数这个对象上定义了一些属性和方法,下面我们逐一来介绍这 ...

  9. HTML5中的对象的拖拽

    拖拽: draggable="true"页面上就能实现拖拽事件: ondragstart 拖拽开始事件 ondrag 拖拽中 ondragend 拖拽结束事件 投放区事件: ond ...

随机推荐

  1. List排序Collections.sort 重写compare

    static List<Integer> intList = Arrays.asList(2,5,7, 3, 1); public static void main(String[] ar ...

  2. pom.xml复制过来的代码报错-Maven expected START_TAG or END_TAG not TEXT (positionTEXT se

    场景 编译器:IDEA 在网上看一些小实例,跟着做的时候会复制pom.xml文件的代码来加载依赖包.首先需要确定你复制过来的代码本身是没有错的,在复制一些pom.xml文件代码时,有时候会报错.原因是 ...

  3. [总结]web前端常用JavaScript代码段及知识点集锦

    DOM相关 判断浏览器是否支持placeholder属性 function placeholderSupport() { return 'placeholder' in document.create ...

  4. 【工具相关】ionic-通过nmp安装最新版本的 cordova 和 ionic

    一,命令行下输入: sudo npm install -g cordova ionic 用来安装最新版本的cordova和ionic. 如下图所示: 二,等待一下,如下图所示. 三,用命令 npm u ...

  5. 【读书笔记】iOS-Nib的一些知识

    Apple在Xcode4.2中推出用于iOS应用故事版概念. 标识:Identity(标识)检查器最常用于为用户界面元素或者控制器分配一个自定义类. 属性:Attributes(属性)检查器在微调用户 ...

  6. 【读书笔记】iOS-离线可用的Web应用

    众所周知,网页不光需要靠互联网接入访问才能提供各种形式的服务,而且连网页自身的各种设计元素也需要在有网接入的情况上才能获得. 但借助于HTML5的离线特性,我们可以通过把各种类型的资源都储存在Web应 ...

  7. 如何解决用CMake未定义引用`JNI_CreateJavaVM'?

    我需要从C ++运行Java,一般来说问题已经解决,但我的make系统或脚本出了问题,有一个创建JVM的C ++文件: #include <jni.h> #include <iost ...

  8. [Android] 设置AlertDialog中按钮的可用(Enable)状态

    弹出一个保存文件的对话框,要控制输入内容限制,同时内容为空时保存按钮不可用. 原文地址请保留http://www.cnblogs.com/rossoneri/p/4140184.html 直接上代码: ...

  9. python第九十一天----第十六周作业

    实现功能: 1.非编辑模式 ​ 可以对每行进行选择,全选,取消,反选 : 2.编辑模式 ​ 进入编辑模式时: 如果行被选中,则被选中的行变为可编辑状态,未选中则不改变 ​ 退出编辑模式时: 保存所有的 ...

  10. Git的gc功能

    http://blog.csdn.net/lihuanshuai/article/details/37345565 Git的底层并没有采用 CVS.SVN 底层所采用的那套增量式文件系统,而是采用一套 ...