学习参考资料javascript.info
Range
基本概念
- Range翻译过来是范围,可以理解为是一对「边界点」(范围起点、范围终点)
- 它可以直接用new来创建。
let range = new Range();
- 我们可以用
range.setStart(node, offset)andrange.setEnd(node, offset)来设定边界起始。其中node可以是文本结点也可以是元素结点。
(1)当node是文本结点时:
<body>
<p id="para">Alex</p>
</body>
<script>
const $p = document.getElementById('para');
let range = new Range();
range.setStart($p.firstChild, 3);
range.setEnd($p.firstChild, 4);
console.log(range.toString()); // x
range.setStart($p.firstChild, 0);
range.setEnd($p.firstChild, 1);
console.log(range.toString()); // A
range.setStart($p.firstChild, 1);
range.setEnd($p.firstChild, 4);
console.log(range.toString()); // lex
// 对于文本可以理解为:offset设置为a,b可以理解为选取index为a到index为b-1的字符
// 如果offset大于文本长度会报错
</script>
(2)当node是元素结点是:
node是元素结点时,offset需要设置为它子结点的index。例如,p的子结点及其对应index如下: (下划线代表空格)
- index0: Alex_
- index1: and
- index2: his friends
<body>
<p id="para">Alex <span>and</span> his friends </p>
</body>
const $p = document.getElementById('para');
let range = new Range();
range.setStart($p, 0); // 从index选到index0
range.setEnd($p, 1);
console.log(range.toString()); // Alex_
range.setStart($p, 1); // 从index 1 选到 index1
range.setEnd($p, 2);
console.log(range.toString()); // and
range.setStart($p, 0); 从index0 选到index2
range.setEnd($p, 3);
console.log(range.toString()); //Alex and his friends
range.setStart($p.firstChild, 4);// 从alex的index 4(空格)开始到p的结束
console.log(range.toString()); //_and his friends
属性
我们上面创建的Range对象(上面代码块输出为and的部分)有如下属性:
startContainer,startOffset开始位置的容器是p, 开始的offset是1endContainer,endOffset结束位置的容器是p,结束的offset是2collapsed如果为true则代表开始和结束位置是一样的,也就是说range内容是空的commonAncestorContainerrange内最近的公共祖先。这里是p
方法
(1)设置起始点的方法
前面已经用到了两个方法setStart和setEnd。其他的还有:
setStartBefore(node)set start at: right beforenodesetStartAfter(node)set start at: right afternodesetEndBefore(node)类似上面setEndAfter(node)selectNode(node)让Range包含整个节点selectNodeContents(node)让Range包含整个结点的内容collapse(toStart)设定是否起始点一样cloneRange()创建一个和原Range起始点相同的Range
一些小试验: ex1
<p id="para">Alex <span>and</span> his friends </p>
<div id="div">Michael <span id="andTwo">and</span> his family </div>
-----
const $div = document.querySelector('#div');
const $para = document.querySelector('#para');
const $andTwo = document.querySelector('#andTwo');
let range = new Range();
range.setStartBefore($div); // 从div开始
range.setEndAfter($andTwo); // 到and之后结束
console.log(range.toString()); // Michael and
ex2 试验selectNode和selectNodeContents
const $div = document.querySelector('#div');
const $para = document.querySelector('#para');
const $andTwo = document.querySelector('#andTwo');
let range1 = new Range();
let range2 = new Range();
range1.selectNode($para);
console.log(range1);
range2.selectNodeContents($para);
console.log(range2);
通过打印两个Range可以看出,
- 起止offset不同。
- 起止容器不同。
selectNode中,容器是body(p的直接父元素),offset分别是1和2,也就是选中body的index为1的子元素(body子元素中,index是0的是空白文本,然后接下来p是index1)。它相当于是 range3.setStart($body, 0); range3.setEnd($body, 2);
而selectNodeContents的容器是p,是从index是0的子元素选到index是2的子元素(也就是全部子元素)。
(2)编辑内容
deleteContents()extractContents()– remove range content from the document and return as DocumentFragmentcloneContents()– clone range content and return as DocumentFragmentinsertNode(node)– insertnodeinto the document at the beginning of the rangesurroundContents(node)– wrapnodearound range content. For this to work, the range must contain both opening and closing tags for all elements inside it: no partial ranges like<i>abc.
还需要学习selection,这个放到之后有时间再补充。