range 标准化之获取

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 基本相同)。

(0)

相关推荐

  • range 标准化之获取

    w3c range range 用来表示用户的选择区域,这块选择区域由两个边界位置界定,而位置则由其容器以及偏移量构成,称作 container 与 offset .如下是一个简单的位置示例: 复制代码 代码如下: <p><span>文字</span>^<span>文字</span></p> 其中 ^ 表示一个位置,则 container 为父节点 p,offset即为相对于父节点的偏移量为1.需要注意的是当container为元素节

  • 批处理bat标准化获取当前系统日期的几种方法

    操作系统不同,日期格式也可能不同: 星期二 2008-07-29 2008-07-29 星期二 07/29/2008 Tue Tue 07/29/2008 再考虑到中.英之外的其它语言的操作系统,日期格式的种类实在太多了. 要想标准化地获取当前系统日期2008-07-28,直接截取%date%变量的方法是不行的. [方案一]BAT + REG @echo off rem 无法保证在中.英之外的其它语言的操作系统上得到正确结果 for /f "delims=" %%a in ('reg

  • javascript获取以及设置光标位置

    一. 获取光标位置: // 获取光标位置 function getCursortPosition (textDom) { var cursorPos = 0; if (document.selection) { // IE Support textDom.focus (); var selectRange = document.selection.createRange(); selectRange.moveStart ('character', -textDom.value.length);

  • python3获取文件中url内容并下载代码实例

    这篇文章主要介绍了python3获取文件中url内容并下载代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2019-12-25 11:33 # @Author : Anthony # @Email : ianghont7@163.com # @File : get_video_audio_file.py import xlrd

  • Ruby的语法和语言特性总结

    Ruby是一种解释型.面向对象.动态类型的语言.Ruby采取的策略是在灵活性和运行时安全之间寻找平衡点.随着Rails框架的出现,Ruby也在2006年前后一鸣惊人,同时也指引人们重新找回编程乐趣.尽管从执行速度上说,Ruby谈不上有多高效,但它却能让程序员的编程效率大幅提高.本文将讲述Ruby语言的基础语言特性,包括基本的语法及代码块和类的定义. 1. 基础 在Ruby交互命令行中输入以下命令(>>为命令行提示符,=>为返回值:下文将把=>符号和语句写在一行内表明其返回值): &

  • Python实现Dijkstra算法

    Dijkstra算法 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 迪杰斯特拉算法是求从某一个起点到其余所有结点的最短路径,是一对多的映射关系,是一种贪婪算法 示例: 算法 算法实现流程思路: 迪杰斯特拉算法每次只找离起点最近的一个结点,并将之并入已经访问过结点的集合(以防重复访问,陷入死循环),然后将刚找到的

  • python使用tkinter库实现五子棋游戏

    本文实例为大家分享了python实现五子棋游戏的具体代码,供大家参考,具体内容如下 一.运行截图: 二.代码 # 用数组定义一个棋盘,棋盘大小为 15×15 # 数组索引代表位置, # 元素值代表该位置的状态:0代表没有棋子,1代表有黑棋,-1代表有白棋. from tkinter import * from tkinter.messagebox import * class Chess(object): def __init__(self): ############# # param # #

  • Python+opencv 实现图片文字的分割的方法示例

    实现步骤: 1.通过水平投影对图形进行水平分割,获取每一行的图像: 2.通过垂直投影对分割的每一行图像进行垂直分割,最终确定每一个字符的坐标位置,分割出每一个字符: 先简单介绍一下投影法:分别在水平和垂直方向对预处理(二值化)的图像某一种像素进行统计,对于二值化图像非黑即白,我们通过对其中的白点或者黑点进行统计,根据统计结果就可以判断出每一行的上下边界以及每一列的左右边界,从而实现分割的目的. 下面通过Python+opencv来实现该功能 首先来实现水平投影: import cv2 impor

  • python使用Pandas库提升项目的运行速度过程详解

    前言 如果你从事大数据工作,用Python的Pandas库时会发现很多惊喜.Pandas在数据科学和分析领域扮演越来越重要的角色,尤其是对于从Excel和VBA转向Python的用户. 所以,对于数据科学家,数据分析师,数据工程师,Pandas是什么呢?Pandas文档里的对它的介绍是: "快速.灵活.和易于理解的数据结构,以此让处理关系型数据和带有标签的数据时更简单直观." 快速.灵活.简单和直观,这些都是很好的特性.当你构建复杂的数据模型时,不需要再花大量的开发时间在等待数据处理的

  • Python常见MongoDB数据库操作实例总结

    本文实例讲述了Python常见MongoDB数据库操作.分享给大家供大家参考,具体如下: MongoDB 是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型.Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可

随机推荐