作家
登录

range 标准化之获取

作者: 来源:www.28hudong.com 2013-03-30 00:45:12 阅读 我要评论

w3c range range 用来表示用户的选择区域,这块选择区域由两个边界位置界定,而位置则由其容器以及偏移量构成,称作 container 与 offset .如下是一个简单的位置示例: 复制代码 代码如下: <p><span>文字</span>^<span>文字</span></p> 其中 ^ 表示一个位置,则 container 为父节点 p,offset即为相对于父节点的偏移量为1。需要注意的是当container为元素节点时,其偏移量单元为节点,即从容器的第一个子节点到当前位置处所经历的子节点数。 相应的,container也可以是文字节点,这时container 为 textnode ,而offset则为从该textnode到当前位置所经历的 utf-16 字符个数(意味着,中文和英文计数一样,不是字节计数)。如 复制代码 代码如下: <p><span>文字</span><span>01234^567</span></p> 上例中 container 为 "01234567" 这个文字节点,而offset 则是从该文字节点第一个字符到当前位置所经历的字符个数即5. ie range 简要介绍一下,具体请查阅 msdn ie range 没有清晰的容器与偏移量的概念,但是基本思想和 w3c range 一样,具备同等的表达能力,分为 textrange 与 controlrange,包含一系列的方法。 textrange 不是从字面意义上的单纯文本,而是表示用户的选择区域内容(可用其htmlText获取完整内容),其操作方式大多是以文字为单元而不是 dom 树节点。 controlrange 字面意思表示获取选择 控件 ,实际是有些元素(div,img,object...)处于可编辑状态时,经单击可将整个元素选中。 ie 标准化之获取 从上面介绍可见,w3c 的range更规范,更清晰,其 container 与 offset 的概念更直观,当我们需要对range关联dom节点进行操作时,无疑 container ,offset是必不可少的,而 ie range 则没有显示的提供获取这两个关键变量的方法, 前面说过 ie range 其实具备 w3c range 等价的功能,那么就可以结合其提供的一系列方法推导出这两个变量。 范围对象获取: 范围对象有两种获取方式: 1.从当前选择区域获得 range ,可调用 复制代码 代码如下: document.selection.createRange() 方法根据目前选择,返回 TextRange 或 ControlRange 实例。 2.从元素创建 range ,可调用 复制代码 代码如下: oControlRange = object.createControlRange() Js代码 oTextRange = object.createTextRange() 前一种 之能在 body,element上调用,而后一种 可在大多数元素上调用。调用后则该范围完全覆盖调用元素。相当于 moveToElementText 。textrange 标准化: 首先介绍下用到的几个方法: collapse :根据参数将结束位置重合到开始位置(true)或开始位置重合到结束位置(false)。 parentElement :获取包围选择区域的元素节点,如下例调用后得到span节点。 复制代码 代码如下: <span>文^字</span> moveToElementText (Node a) :将选择区域变更为 a ,起始位置为 a 的前后,如作用到如下 span 节点后: 复制代码 代码如下: ^<span>文字</span>^ range1.compareEndPoints('XxToYy',range2) :xx,yy 可以为 Start 或 End,取 range1 的 xx 位置和 range2 的 yy 位置比较,根据前后顺序返回-1,1,0表示重合。 range1.setEndPoint("XxToYy",range2) :xx,yy 可以为 Start 或 End,将range1的xx位置设为range2的yy位置。 转化: 有了上面的5个方法就可以开始我们的标准化第一步:获取位置,首先给出操作例子: (绿块表示文字节点,注意:正常手工编写页面情况下不会出现两个相邻的文字节点,这里使用 splitText 强制分离 ) 当我们将选择区域collapse后,可能有上述四个位置:1,2,3,4,其中 1,4 相邻元素节点最简单: 1,4位置 标准化: 1.根据 parentElement 得到包含位置的节点 p ,即为该位置的container 2.对container的所有元素子节点,一一验证是否和已知位置相邻,验证方法即为:通过 moveToElementText 新建range包围子节点,再通过 compareEndPoints 比较是否新建 range 的前后位置是否和当前位置重合: 复制代码 代码如下: range = range.duplicate(); range.collapse(start); var parent = range.parentElement(), siblings = parent.childNodes; for (var i = 0; i < siblings.length; i++) { var child = siblings[i]; if (child.nodeType == 1) { var tr = range.duplicate(); tr.moveToElementText(child); //子元素节点开始位置比较 var comparisonStart = tr.compareEndPoints('StartToStart', range), //子元素节点结束位置比较 comparisonEnd = tr.compareEndPoints('EndToStart', range); //开头已经在当前位置后面,没必要继续比了 if (comparisonStart > 0) break; else if (!comparisonStart || comparisonEnd == 1 && comparisonStart == -1) return { container: parent, offset: i }; else if (!comparisonEnd) return { container: parent, offset: i + 1 }; } } 2,3位置 标准化: 2 表示位置在两个文字节点之间,container为 p ,由于moveToElementText 无法作用文字节点,则只能另想他法。 3 表示位置处于文本节点中间,此时 container 为文本节点,而 offset 则要数字符数了。 1.当到达 1 位置时,停止。 2.新建range ra,开始位置为 1,结束位置为2或3,取得 ra的所有字符数 ra_textlength,对从位置1开始往右的每个文字节点,从 ra_textlength 中减去其长度(data.length),当 ra_textlength 为0时,代表当前位置为2,而当前经过的文字节点数目即为offset。 当 ra_textlength 为负数时,表示当前位置为3, 当前的文字节点即为位置3 的container,ra_textlength 的上一个值则是offset。 示例: 复制代码 代码如下: <p id="test"><strong>粗体</strong>普通|文字<i>斜体</i></p> <script> document.getElementById("test").childNodes[1].splitText(2); </script> 标准化 demo controlrange 标准化 controlrange 就很简单了,由 item(index) 方法得到选择元素,结合其parentNode 就可以得到标准化表示了。 PS : 关于输入框的范围读取 由于规范规定输入框的选择区域和页面选择区域是分离的,输入框的选择区域有不同的获取方式 (IE 基本相同)。

  推荐阅读

  基于jquery的多彩百分比 动态进度条 投票效果显示效果实现代码

打造 漂亮 动态 友好的 精选随机色彩 投票百分比展示 效果 HTML结构: 复制代码 代码如下: <ul class="vote-box-list clearfix" id="appVoteBox"> <li class="vl-item" id="voteItem0" > <div class="vote-item->>>详细阅读


本文标题:range 标准化之获取

地址:http://www.17bianji.com/kaifa2/JS/24219.html

关键词: 探索发现

乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

网友点评
自媒体专栏

评论

热度

精彩导读
栏目ID=71的表不存在(操作类型=0)