CKEditor5——Position源码分析(二)

CKEditor5——Position源码分析(二)

上一节,我们学习了Position的基础知识,包括怎么寻找它的parent属性,它的path是什么意思?

今天我们看另一个方法,两个Position之间的关系是什么,也就是这个方法:

compareWith( otherPosition ) → PositionRelation

compareWith( otherPosition ) {
	if ( this.root != otherPosition.root ) {
		return 'different';
	}

	const result = compareArrays( this.path, otherPosition.path );

	switch ( result ) {
		case 'same':
			return 'same';

		case 'prefix':
			return 'before';

		case 'extension':
			return 'after';

		default:
			return this.path[ result ] < otherPosition.path[ result ] ? 'before' : 'after';
	}
}

从以上的代码可以看出,如果两个Position的根节点不一样,它们一定是不同的。它们之间关系的比较是通过一个工具方法:compareArrays( this.path, otherPosition.path );

下面我们看看这个方法:

export default function compareArrays( a, b ) {
	const minLen = Math.min( a.length, b.length );

	for ( let i = 0; i < minLen; i++ ) {
		if ( a[ i ] != b[ i ] ) {
			// The arrays are different.
			return i;
		}
	}

	// Both arrays were same at all points.
	if ( a.length == b.length ) {
		// If their length is also same, they are the same.
		return 'same';
	} else if ( a.length < b.length ) {
		// Compared array is shorter so it is a prefix of the other array.
		return 'prefix';
	} else {
		// Compared array is longer so it is an extension of the other array.
		return 'extension';
	}
}

首先获取两个数组长度最短的值minLen,然后比较前minLen个值,如果不相同的话没救返回不相同的位置的索引;如果前minLen个值都相同,如果a的长度比b的长度小,那么返回prefix;如果a的长度大于b的长度,那么返回extension;否则长度相同,值也相同,则返回same;

有了这个工具方法,我们可以知道,两个Position的关系可能有四种same,before,after,different

如果他们的path数组的值是一样的,那么这两个Position的关系是same;

如果当前PositionpathotherPositionpath之前,那么认为当前PositionotherPosition之前,否则就是之后。

这里的一个默认值是比较它们path的第一个不相等的值对应的大小,小的在前面,大的在后面。

 

有了以上的比较两个Position关系的方法,我们可以看看其他的几个方法,比如:

isAfter( otherPosition ) → Boolean

isBefore( otherPosition ) → Boolean

isEqual( otherPosition ) → Boolean

isTouching( otherPosition ) → Boolean

都是调用我们以上分析的方法来实现的,这里我们重点看看最后一个:

isTouching( otherPosition ) {
	let left = null;
	let right = null;
	const compare = this.compareWith( otherPosition );

	switch ( compare ) {
		case 'same':
			return true;

		case 'before':
			left = Position._createAt( this );
			right = Position._createAt( otherPosition );
			break;

		case 'after':
			left = Position._createAt( otherPosition );
			right = Position._createAt( this );
			break;

		default:
			return false;
	}

	// Cached for optimization purposes.
	let leftParent = left.parent;

	while ( left.path.length + right.path.length ) {
		if ( left.isEqual( right ) ) {
			return true;
		}

		if ( left.path.length > right.path.length ) {
			if ( left.offset !== leftParent.maxOffset ) {
				return false;
			}

			left.path = left.path.slice( 0, -1 );
			leftParent = leftParent.parent;
			left.offset++;
		} else {
			if ( right.offset !== 0 ) {
				return false;
			}

			right.path = right.path.slice( 0, -1 );
		}
	}
}

这里我们先看看什么是touching:检查此位置是否接触给定位置。当它们之间的范围内没有文本节点或空节点时,位置接触。从技术上讲,这些位置并不相同,但在许多情况下,它们非常相似甚至无法区分。

这里我们思考一下,两个Position接触的情况有哪些:

1、两个Position一模一样。

2、第一个Position在前面,第二个Position在后面,但是它们之间没有空隙

3、第一个Position在后面,第二个Position在前面,它们之间也没有空隙。

以上的方法实现就是针对的这三种情况,感兴趣的可以去仔细分析一下。

版权声明:著作权归作者所有。

相关推荐

使用Swift 3/Swift 4扫描二维码

iOS的AVFoundation内置了对二维码和条形码扫描的支持。使用AVFoundation扫描二维码的功能需要几件事:创建AVCaptureSession,用于捕获二维码创建预览捕获二维码成功后,委派回调来处理二维码的meta信息下面的例子是基于UIViewController开发的扫描二维码Controller,使用AVCaptureMetadataOutputObjectsDelegate

JavaScript使用for...in迭代数组分析

for...in与其说是迭代,更恰当的说法应该是枚举。其目的是用来枚举object对象的属性,包括对象所继承的属性。有部分人会使用for...in来迭代数组,这是一种误用。以下对使用for...in迭代数组分析。问题一var a = ['a','b']; a[5] = 'e'; for (var x in a

Android安装错误App not installed原因分析

App not installed可能原因:App与Android设备或版本不兼容使用了不同的证书签名不同版本的apk,这会导致重新安装失败。app的签名不正确,检查下是否与选择的Signature Version相关v2为Android 7新增的签名方式。可以参考APK signature scheme v2

使用awk分析nginx访问日志access.log的ip

access.log为nginx的访问日志,默认路径在/var/log/nginx/access.log 分析access.log的ip命令如下:awk '{print $1}' access.log |sort|uniq -c|sort -n 命令里使用awk过滤出访问的ip使用sort对ip排序对排序后的ip进行统计,统计每一个ip访

Java源码分析:产生随机数Random与ThreadLocalRandom的区别

Java用于产生随机数的方法主要有两种:java.util.Random和java.util.concurrent.ThreadLocalRandom。Random从Jdk 1.0开始就有了,而ThreadLocalRandom是Jdk1.7才新增的。简单从命名和类所在的包上看,两者的区别在于对并发的支持。RandomRandom是一个伪随机数生成器,它内置了一个种子数seed。获取随机

Rxjs expand的用法分析

Rxjs的expand()函数声明:public expand(project: function(value: T, index: number), concurrent: number, scheduler: Scheduler): Observable expand()会递归调用project函数,project函数把源值映射为一个Observable,每次递归

(转)Android 5.1.1 源码目录结构

转自:http://blog.csdn.net/tfslovexizi/article/details/51888458最近公司培训新同事,我负责整理一点关于android的基础知识,遥想当年,刚接触android,也是一头雾水,啥都不懂,就是靠看文档和视频,对android有一个初步了解,然后就通过查看源码,才有更深入的了解。android有成千上万,说太少了,是成百万上亿的代码,当然要全部都了

JIT的分层编译和逃逸分析

JIT到底在Java的运行中发挥了什么作用呢?根据查阅到的资料,一个作用是做分层编译,一个是做对象的逃逸分析。对于循环体中的代码,循环到一定的程度的时候,就会被再次被编译,编程执行速度更加迅速的代码。对于新建的对象,讲过逃逸分析,如果数据不会逃逸,则将数据放在栈上,不再在heap上新建这个对象。这样的好处是:避免了在堆上新建的锁堆导致的资源损耗不需要GC

CKEditor5——模型理解(二:Node)

上一节我们理解了基本的CK5的模型基本信息,今天我们来学习一些模型的API。节点说明首先,需要理解的就是模型的节点。在这一点上,CK5的模型节点和dom的节点有点类似,也有一些不同。我会在文章中一一介绍。节点是模型树的基本结构。它是模型中不同节点类型的一种抽象。这里需要指出的一点是:如果一个节点从模型树中分离出来,你可以使用它的 API 来操作它。但是,非常重要的是,已经附加到模型树的节点只能通过

CKEditor5——模型理解(五:Position, Range, Selection)

今天我们继续学习CK5中模型的一些知识,主要包括:Position, Range, Selection首先,我们需要知道:position表示模型树中的一个位置。模型的位置有两部分组成:root,path。即位置由其根和该根中的路径表示。位置基于偏移量,而不是索引。这意味着两个文本节点 foo 和 bar 之间的位置偏移为 3,而不是 1。由于模型中的位置由位置根和位置路径表示,因此可以创建不存在