DOM 之Range(范围)
-------《javascript高级程序设计》 12.4 范围 笔记-------
DOM2级在Document类型中定义了createRange()方法,在兼容DOM的浏览器中,这个方法属于Document对象。可以使用HasFeature方法来检测浏览器是否支持范围
var supportsRange = document.implementation.hasFeature(‘Range’, ‘2.0’)
var alsoSupportsRange = (typeof document.createRange == ‘function’);
一、如果浏览器支持Range,就可以使用createRange()来创建DOM范围
var range = documemt.createRange();
新创建的范围直接与创建它的文档关联在一起,不用用于其他文档。每一个范围由一个Range类型的实例表示。 它有很多属性及方法
1. startContainer: 包含范围起点的节点(即选区中第一个节点的父节点)
2. startOffset: 范围在startComtainer中起点的偏移量,如果startContainer是文本节点、注释节点或CDATA节点,那么startOffset就是范围起点之前的跳过的字符数量,否则,startOffset就是范围中第一个子节点的索引。
3. endContainer 包含范围终点的节点(即选区中最后一个节点的父节点)
4. endOffset: 范围在endContainer中节点的偏移量(与startOffset遵循相同的取值规则)
5. commonAncestorContainer: startContainer和endContainer共同的祖先节点在文档树中位置最深的那个
二、用DOM范围实现简单选择
选用的方法 selectNode() 或者selectNodeContents()
1.这两个方法都接受一个参数,即一个DOM节点。但selectNode()方法选择整个节点,包括其子节点,而selectNodeContents()方法只是选择节点的子节点,
range<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
<p id="p1"><b>hello</b>world</p>
</body>
</html>
rangevar p1 = document.getElementById('p1');
//创建范围
var range1 = document.createRange();
var range2 = document.createRange();
//实例化范围
range1.selectNode(p1);
range2.selectNodeContents(p1);
//检测范围里的一些属性及方法
range1.startContainer // body
range1.startOffset // 1 空格文本是一个文本节点
range1.endContainer //body
range1.endOffset // 2 只选中一个子节点
range1.commonAncestorContainer //body range2.startContainer //p1
range2.startOffset // 0
range2.endContaner //p1
range2.endOffset // 2
range2.commonAncestorContainer //p1
------为了更精细的控制将哪些节点包含在范围中,还可以使用下列方法 ------
1. setStartBefore(refNode) 将范围的起点设置在refNode之前,因此refNode也就是范围选区中的第一个子节点,同时会将startContainer属性设置为refNode.parentNode,将startOffset属性设置为refNode在其父节点的childNodes集合中的索引
2. setStartAfter(refNode) 将范围的起点设置在refNode之后,因此refNode也就不在范围之内了,其下一个同辈节点才是选区中的第一个子节点,同时会将startContainer属性设置为refNode.aprentNode,将startOffset属性设置为refNode在其父节点的childNodes集合中的索引加1;
3. setEndBefore(refNode): 将范围的终点设置在refNode之前,因此refNode也就不在范围之内了,其上一个同辈节点才是范围选区中的最后一个子节点。同时会将endContainer属性设置为refNode.parentNode,将endOffset属性设置为refNode在其父节点的childNodes集合中的索引;
4. setEndAfter(refNode) 将范围的终点设置 在refNode之后,因此refNode也就是范围选区中的最后一个子节点。同时会将endContainer属性设置为refNode.parentNode,将endOffset属性设置为refNode在其父节点的childNodes集合中的索引加1
---- 用DOM范围实现复杂选择 -----
要实复杂的范围就使用setStart() 和setEnd() 方法,这两个方法都接受两个参数: 一个参照节点和一个偏移量值
setStart() 参照节点会变成startContainer,而偏移量值会变成startOffset
setEnd() 参照节点会变成endContainer,偏移量会变成endOffset
用这两个方法重写前面selectNode()与selectNodeContents()方法
rangevar range1 = document.createRange();
var range2 = document.createRange();
var p1 = document.getElementById('p1');
var p1Index = -1, i, len;
//检测p1的索引值
for(i = 0,len = p1.parentNode.childNodes.length; i<len; i++){
if( p1.parentNode.childNodes[i] == p1){
p1Index = i;
break;
}
}
range1.setStart(p1.parentNode, p1Index);
range1.setEnd(p1.parentNode, p1Index+1);
range2.setStart(p1,0);
range2.setEnd(p1,p1.childNodes.length);
setStart() 与setEnd()方法的运用
rangehelloNode = p1.firstChild.firstChild // 文本节点 'hello'
worldNode = p1.lastChild // 文本节点 ' world'
range = document.createRange()
range.setStart(helloNode, 2);
range.setEnd(worldNode,3)
//这个范围就是 'llo world'
range.startContainer //hello
range.endContainer //world
range.startOffset // 2 字符在文本节点的位置
range.endOffset // 3
range.commonAncestorContainer // p#p1
-----操作DOM范围中的内容-----
在创建范围时,内部会为这个范围创建一个文档片段.范围所属的全部节点都被添加到了这个文档片段中,范围知道自身缺少哪些开标签和闭标签,它能够重新构建有效的DOM结构以便我们对其进行操作
针对上面的例子,选区变为了 ‘llo’</b>wo 不是一个有效的DOM结构,但范围会自动添加缺少的,最终变成了
<p><b>he</b><b>llo</b> wo rld</p> 范围内的文档片段是
1. deleteContents() 从文档中删除范围所包含的内容,没有返回值
2.extractContents() 也会从文档中移除范围选区,但会返回范围的文档片段,可以进行其他作用
3.cloneContents() 创建范围对象的一个副本,然后在文档的其他地方插入该副本; 在调用方法之前,拆分的节点并不会产生格式良好的文档片段,换句话说,原始的HTMl在DOM被修改之前会始终保持不变
4.insertNode(Node) 向范围选区的开始处插入一个节点
5. surroundContents() 环绕范围内容插入内容, 接受一个参数,即环绕范围插入的节点
在环绕范围插入内容时,后台会执行下列步骤
1) 提取出范围中的内容(类似执行extractContent());
2) 将给定节点插入到文档中原来范围所在的位置上;
3) 将文档片段的内容添加到给定节点中;
6. 折叠DOM范围
就是范围中未选择文档的任何部分;collapse()方法来折叠范围,这个方法接受一个参数(布尔值) true 表示折叠到范围的起点,false表示折叠到范围的终点。要检测范围已经折叠完毕,可以检查collapsed属性
检测某个范围否处于折叠状态,可以帮我们确定范围中的两个节点是否紧密相邻。 将一个范围设置第一个节点的终点,另一个范围设置为第二个节点的起点,如果两个节点是相邻了 这个范围就折叠完毕,
7. 比较DOM范围
在有多个范围的情况下,可以使用compareBoundaryPoints() 方法来确定这些范围是否有公共的边界(起点和终点)。这个方法接受两个参数:表示比较方式的常量值和要比较的范围。表示比较方式的常量值如下所示
Range.START_TO_START(0) 比较第一个范围和第二个范围的起点
Range.START_TO_END(1) 比较第一个范围的起点和第二个范围的终点
Range.END_TO_END(2) 比较第一个范围和第二个范围的终点
Range.END_TO_START(3) 比较第一个范围的终点和第一个范围的起点
--- compareBoundaryPoints()方法可能的返回值如下:
如果第一个范围中的点位于第二个范围中的点之前,返回-1;
如果两个点相等。返回0;
如果第一个范围中的点位位于第二个范围中的点之后,返回1
range<!DOCTYPE html>
<html>
<head>
<title>范围</title>
<meta charset="utf-8">
</head>
<body>
<p id="p2">before</p>
<p id="p1"><b>hello</b> world!</p>
<p id="p3">after</p>
<script type="text/javascript">
var p1 = document.getElementById('p1' ),
p2 = document.getElementById('p2' ),
p3 = document.getElementById('p3' ),
range1 = document.createRange(),
range2 = document.createRange();
range1.selectNodeContents(p1);
range2.selectNodeContents(p1);
range2.setEndBefore(p1.lastChild);
range1.compareBoundaryPoints(Range.START_TO_START,range2)
range1.compareBoundaryPoints(Range.END_TO_END,range2)
</script>
</body>
</html>
8.cloneRange() 复制范围
9. detach() 从创建范围文档中分离出该范围。从而让垃圾回收机制回收其内存
range.detach();
range = null
--------------------------------ie的范围----------------------
IE专有的文本范围(text range) 文本范围处理的主要是文本(不一定是DOM节点),通过<body>,<button>.<input>.<textarea> 等这几个元素可以调用createTextRange()方法来创建文本范围
1.findText() 会找到第一次出现的给定文本,并将范围移过来环绕该文本。如果没找到文本,返回false,否则返回true
textRange<p id="p1"><b>hello</b>world</p> var range = document.body.createTextRange();
var found = range.findText('hello');
文本'hello’就被包含在范围之内。可以检测范围的text属性,来确认(这个属性返回范围中包含的文本),或者可以检查findText()的返回值
还可以为findText()传入另一个参数,即表示向哪个方向继续搜索的数值,负值表示应该从当前位置向后搜索,正值表示从当前位置向前搜索
2.moveToElementText() 接受一个DOM元素,并选择该元素的所有文本,包含HTML标签,(与selectNode类似)
可以使用range的htmlText属性来取得范围的全部内容。包含HTMl和文本
3. parentElement() (与commonAncestorContainer属性类似)
-----使用IE范围实现复杂的选择---
1. move() moveStart() moveEnd() expend() 这四个方法都接受两个参数,移动单位和移动单位的数量
移动单位是下列的一种字符串值
‘character’ 逐个字符地移动
'word’ 逐个单词(一系列非空字符)地移动
'sentence’ 逐个句子(一系列以句号、问号或叹号结尾的字符)地移动
'textedit’ 移动到当前范围选区的开始或结束位置
moveStart() moveEnd() 可以移动范围的起点和终点,移动的副度同单位数量指定 (正值表示缩小范围,负值表示增大范围)
expand() 可以将范围规范化。(将任何部分选择的文本全部选中)
move() 方法会首先折叠当前范围(让起点和终点相等),然后再将移动指定的单位数量
调用move()之后,范围的起点与终点相同,因此必须再使用moveStart() 或moveEnd()创建新的选区
2.操作范围中的内容可以使用text属性或pasteHTML()方法,
text属性是可读写的 ,可以获取范围内的文本,也可以设置范围内的文本
pasteHTMl() 方法可以设置范围内的HTMl,插入HTMl时可能会导致格式不正确的HTMl存在(范围选取时截取了标签)
3. 折叠范围
collapse() 参数为布尔值,true 折叠到起点。false折叠到终点
IE没有collapsed属性来检测是否折叠完毕,但可以使用boundingWidth属性。该属性返回范围的宽度(以像素为单位),折叠完毕后boundingWidth返回值为0 (boundingTop,boundingHeight,boundingWidth,boundingLeft
4. 比较IE范围
compareEndPoints() 方法 (与DOM范围中的compareBoundaryPoints()方法类似) 接受两个参数:比较的类型和要比较的范围。比较类型的取值范围是下列几个字体串
'startToStart’ , ‘startToEnd’ ‘EndtoEnd’ ‘EndToStart’
compareEndPoints()方法返回值(与DOM的compareBoundaryPoints()方法一样)
如果第一个范围的边界位于第二个范围的边界前面,返回-1;
如果两个边界相同,返回0;
如果第一个范围的边界位于第二个边界的后面,返回1
IE中还有两个方法,用于比较范围
isEqual() 确定两个范围是否相等
inRange() 用于确定一个范围是否包含另一个范围
5.复制IE范围
duplicate()方法可以复制文本范围
DOM 之Range(范围)的更多相关文章
- 使用Dom的Range对象处理chrome和IE文本光标位置
有这样一段js: var sel = obj.createTextRange(); sel.move('character', num); sel.collapse(); sel.select(); ...
- JS 之DOM range对象
DOM范围 DOM中的range对象是DOM2中新定义的接口.通过这个对象可以选择文档中的某个区域,而不必考虑节点的界限. 创建范围 document.createRange()创建一个范围,这个范围 ...
- XML DOM - Range 对象
Range对象 Range对象表示文档的连续范围区域,如用户在浏览器窗口中用鼠标拖动选中的区域. dom标准Range对象 在IE中使用TextRange对象 range对象常用的建立方法在开发中 ...
- DOM拓展
DOM拓展 1.选择符API 所谓选择符API即是根据css选择符选择与某个模式相匹配的DOM元素,jQuery的核心就是通过css选择符查询DOM文档取得元素的引用,从而抛弃了原有繁琐的getELe ...
- JavaScript之DOM等级概述
这两日对DOM等级的理解不是太通透,就进Mozilla官网去看了一下,然后进行了首次的对技术文档的翻译工作,虽然官网也有中文解释,但我想,自己翻译出来时,已经有了原汁原味的理解了吧,这边是做此次翻译的 ...
- dom2和dom3
第十二章 DOM2和DOM3 一.DOM变化 1.针对XML命名空间的变化 2.其他方面的变化 二.样式 1.访问元素的样式 .style 1)DOM样 ...
- js-DOM2,表单脚本
DOM2: 1.DOM2中:创建一个完整的HTML文档 document.implementation.createHTMLDocument("new Doc"); alert(h ...
- Javascript高级编程学习笔记(55)—— DOM2和DOM3(7)操作范围
操作范围中的内容 在创建范围时,内部会为这个范围创建一个文档片段 范围所属的全部节点都会被添加到这个片段中 虽然选取范围可以不是完整的.良好的DOM结构 但是在这个为范围创建的文档片段中,会自己完缺少 ...
- 原生js 复制内容到剪切板
代码: function copyHandle(content){ let copy = (e)=>{ e.preventDefault() e.clipboardData.setData('t ...
随机推荐
- Python学习笔记五--条件和循环
5.1 if语句 没什么好说,if语句语法如下: if expression: expr_true_suit 5.1.1多重条件表达式 单个if语句可以通过布尔操作符and,or,not实现多重条件判 ...
- asp.net2.0app开发。
asp.net app 网站开发:http://www.cnblogs.com/TerryFeng/archive/2009/05/15/1457731.html 在OPERA或M3GATE中设置编码 ...
- macbook air 安装win7系统时,到最后一步要进入win7,需要给PC设置一个用户名,键盘没反应
从 bootcamp安装:1.一定要同时选中第一项 制作usb安装盘和第二项 从网上下载最新的windows支持软件,2.然后再选第三项 安装winDows,3.当进入安装界面时选择你要安装的boot ...
- 《head first python》第一章《初识python》总结
该章主要介绍了python的安装和列表相关 列表主要用了movies做介绍: 1.列表及嵌套列表:movies=["the hodaliy",1975,"zhangyim ...
- IntelliJ Idea取消Could not autowire. No beans of 'xxxx' type found的错误提示
1.问题描述 在Idea的spring工程里,经常会遇到Could not autowire. No beans of 'xxxx' type found的错误提示.但程序的编译和运行都是没有问题的, ...
- 【HDOJ】1011 Starship Troopers
第一道树形DP.很容易理解. #include <cstdio> #include <cstring> #include <cstdlib> #define MAX ...
- iOS 9之Safari广告拦截器(Content Blocker)
金田( github 示例源码) 相对于谷歌对广告拦截的禁止,苹果与之态度截然相反,继Mac版Safari加入广告拦截工具之后,即将到来的iOS9对Safari也引入了内容拦截插件-Content B ...
- Android 应用框架 —— 组件
本文内容根据个人自学整理记录,理解不当之处,希望大家批评指正,大家相互学习,写学习归纳,写博客是个好习惯,希望能够坚持下去. 在前一篇文章当中介绍了Android 的系统框架,主要是为了让大家对And ...
- HDU5266---pog loves szh III (线段树+LCA)
题意:N个点的有向树, Q次询问, 每次询问区间[L, R]内所有点的LCA. 大致做法:线段树每个点保存它的孩子的LCA值, 对于每一次询问只需要 在线段树查询即可. #include <bi ...
- POJ-2240
Arbitrage Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 19063 Accepted: 8069 Descri ...