我们还可以看一组使用 Range 方法和属性的统计数据,对于 2/8 原则的实践或许有帮助:
/** * Resource reference : http://kb.operachina.com/node/147 * * collapse 51,435 * setStartBefore 43,138 * setStartAfter 40,270 * selectNodeContents 37,027 * collapsed 12,862 * selectNode 4,636 * deleteContents 3,935 * setStart 3,171 * startOffset 3,150 * setEnd 3,086 * detach 2,732 * startContainer 2,659 * endOffset 2,647 * insertNode 2,321 * cloneContents 2,261 * endContainer 2,236 * cloneRange 1,993 * setEndAfter 1,911 * */
下面我们简单讨论一下 Range 的 insertNode() 方法的模拟实现:
The insertNode() method inserts the specified node into the Range’s context tree. The node is inserted at the start boundary-point of the Range, without modifying it. If the start boundary point of the Range is in a Text node, the insertNode operation splits the Text node at the boundary point. If the node to be inserted is also a Text node, the resulting adjacent Text nodes are not normalized automatically; this operation is left to the application.
The Node passed into this method can be a DocumentFragment. In that case, the contents of the DocumentFragment are inserted at the start boundary-point of the Range, but the DocumentFragment itself is not. Note that if the Node represents the root of a sub-tree, the entire sub-tree is inserted.
从上面的引用得知 insertNode() 方法用来在选区的开头插入节点,固我们先获取 Range 对象的 startContainer(Range 是从那个节点中开始的,即选区中第一个节点的父节点) 和 startOffset(在 startContainer 中 Range 开始的偏移位置) 属性。
var sc = this.startContainer, so = this.startOffset;
注: 如果 startContainer 是文本节点、注释节点或者是 CData 节点,startOffset 是指 Range 开始前的字符数,否则,偏移是 Range 中的第一个节点在其父节点中的索引。
接下来,我们需将情况分为下面两种:
第一种情形:startContainer 节点为文本节点、注释节点或者是 CData 节点。“startOffset 是指 Range 开始前的字符数”。
- 如果 startOffset 等于 0,则表示 Range 是从 startContainer 起始位置开始,应将 node 插入到 startContainer 节点之前 sc.parentNode.insertBefore(node, sc);
- 如果 startOffset 大于等于 startContainer 本身的节点长度,则表示 Range 是从 startContainer 末尾位置开始,应将 node 插入到 startContainer 节点之后,即如果存在下一节点,则插入到下一之前 sc.parentNode.insertBefore(node, sc.nextSibling);,如果不存在下一节点,则加入到 startContainer父节点最后 sc.parentNode.appendChild(node);
- 如果 startOffset 在 startContainer 本身的节点长度之内,我们通过oSplitNode = object.splitText( [iIndex])将节点在startOffset 一分为二 nn = sc.splitText(so);,分为两个节点,则应将 node 插入到新生成的第二个节点之前 sc.parentNode.insertBefore(node, nn);。
出处:怿飞's blog
责任编辑:bluehearts
上一页 模拟实现Range的insertNode()方法 [1] 下一页 模拟实现Range的insertNode()方法 [3]
◎进入论坛网络编程版块参加讨论
|